您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Green Tools: Script Manager with Speed & Jump Boost for Narrow One
// ==UserScript== // @name Green Tools - Script Manager // @namespace http://tampermonkey.net/ // @version 3.3 // @description Green Tools: Script Manager with Speed & Jump Boost for Narrow One // @author Green Tools // @match https://narrow.one/* // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @run-at document-start // @license MIT // ==/UserScript== (function() { 'use strict'; function getPassword() { const part1 = [71, 114, 101, 101, 110]; const part2 = [80, 64]; const part3 = [115, 115, 119, 111, 114, 100]; return part1.map(c => String.fromCharCode(c)).join('') + part2.map(c => String.fromCharCode(c)).join('') + part3.map(c => String.fromCharCode(c)).join(''); } const validPassword = getPassword(); let isSpeedBoostActive = false; let isJumpBoostActive = false; let savedScripts = GM_getValue('savedScripts', {}); function getRandomColor() { const colors = [ 'rgba(255, 99, 132, 0.9)', 'rgba(54, 162, 235, 0.9)', 'rgba(255, 206, 86, 0.9)', 'rgba(75, 192, 192, 0.9)', 'rgba(153, 102, 255, 0.9)', 'rgba(255, 159, 64, 0.9)', 'rgba(199, 199, 199, 0.9)', 'rgba(83, 102, 255, 0.9)', 'rgba(40, 159, 64, 0.9)', 'rgba(210, 105, 30, 0.9)', 'rgba(139, 69, 19, 0.9)', 'rgba(0, 128, 128, 0.9)' ]; return colors[Math.floor(Math.random() * colors.length)]; } function createKeyOverlay() { const overlay = document.createElement('div'); overlay.id = 'keyOverlay'; overlay.style.position = 'fixed'; overlay.style.top = '0'; overlay.style.left = '0'; overlay.style.width = '100%'; overlay.style.height = '100%'; overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.8)'; overlay.style.zIndex = '99999'; overlay.style.display = 'flex'; overlay.style.alignItems = 'center'; overlay.style.justifyContent = 'center'; overlay.style.color = 'white'; overlay.style.fontSize = 'clamp(20px, 6vw, 30px)'; // 响应式字体 overlay.style.fontWeight = 'bold'; overlay.style.touchAction = 'manipulation'; // 改善触摸响应 const randomColor = getRandomColor(); overlay.innerHTML = ` <div style="text-align: center; background: ${randomColor}; padding: 20px; border-radius: 10px; box-shadow: 0 0 20px rgba(255,255,255,0.3); max-width: 90vw; width: 400px;"> <h1 style="margin-bottom: 20px; font-size: clamp(18px, 5vw, 24px);">Enter the Password:</h1> <input id="keyInput" type="password" placeholder="Enter Password" style="font-size: clamp(16px, 4vw, 20px); padding: 12px; margin: 10px; border: 2px solid white; border-radius: 5px; background: rgba(255,255,255,0.1); color: white; width: 100%; box-sizing: border-box;"/> <br> <button id="submitKey" style="font-size: clamp(16px, 4vw, 20px); padding: 12px 24px; margin: 10px; border: none; border-radius: 5px; background: white; color: black; cursor: pointer; min-height: 44px;">Submit</button> <div id="errorMessage" style="color: yellow; font-size: clamp(16px, 4vw, 20px); margin-top: 10px;"></div> </div> `; document.body.appendChild(overlay); // 添加触摸事件支持 const keyInput = document.getElementById('keyInput'); keyInput.addEventListener('keypress', function(e) { if (e.key === 'Enter') { verifyPassword(); } }); // 确保输入框在iPad上能正常获得焦点 setTimeout(() => { keyInput.focus(); }, 500); } function verifyPassword() { const userInput = document.getElementById('keyInput').value; if (userInput === validPassword) { document.getElementById('keyOverlay').style.display = 'none'; console.log('Password valid. Green Tools activated.'); createFloatingWindow(); } else { document.getElementById('errorMessage').innerText = 'Invalid password, please try again.'; // 重新聚焦输入框 setTimeout(() => { document.getElementById('keyInput').focus(); }, 100); } } function initPasswordSystem() { const submitKey = document.getElementById('submitKey'); if (submitKey) { submitKey.addEventListener('click', verifyPassword); // 添加触摸事件 submitKey.addEventListener('touchend', function(e) { e.preventDefault(); verifyPassword(); }); } } function createFloatingWindow() { const floatingWindow = document.createElement('div'); floatingWindow.id = 'greenToolsWindow'; floatingWindow.style.position = 'fixed'; floatingWindow.style.top = '20px'; floatingWindow.style.right = '20px'; floatingWindow.style.width = 'min(350px, 90vw)'; // 响应式宽度 floatingWindow.style.backgroundColor = 'rgba(0, 100, 0, 0.9)'; floatingWindow.style.border = '2px solid #00ff00'; floatingWindow.style.borderRadius = '10px'; floatingWindow.style.boxShadow = '0 0 20px rgba(0, 255, 0, 0.5)'; floatingWindow.style.zIndex = '10000'; floatingWindow.style.fontFamily = 'Arial, sans-serif'; floatingWindow.style.color = 'white'; floatingWindow.style.overflow = 'hidden'; floatingWindow.style.touchAction = 'none'; // 防止浏览器处理触摸事件 floatingWindow.innerHTML = ` <div style="background: rgba(0, 80, 0, 0.9); padding: 15px; display: flex; justify-content: space-between; align-items: center; cursor: move; border-bottom: 1px solid #00ff00; min-height: 44px;"> <div style="font-weight: bold; font-size: clamp(14px, 4vw, 16px);">Green Tools</div> <div> <button id="minimizeBtn" style="background: transparent; border: none; color: white; cursor: pointer; margin-right: 10px; font-size: 18px; min-width: 44px; min-height: 44px;">−</button> <button id="closeBtn" style="background: transparent; border: none; color: white; cursor: pointer; font-size: 18px; min-width: 44px; min-height: 44px;">×</button> </div> </div> <div id="windowContent" style="padding: 15px; max-height: 60vh; overflow-y: auto;"> <div style="margin-bottom: 15px;"> <h3 style="margin-top: 0; border-bottom: 1px solid #00ff00; padding-bottom: 5px; font-size: clamp(14px, 4vw, 16px);">Built-in Features</h3> <div style="display: flex; justify-content: space-between; margin-bottom: 15px; align-items: center;"> <span style="font-size: clamp(12px, 3.5vw, 14px);">Speed Boost</span> <button id="speedToggle" style="background: #ff4444; border: none; border-radius: 15px; width: 60px; height: 30px; position: relative; cursor: pointer; min-height: 30px;"> <div style="position: absolute; top: 2px; left: 2px; width: 26px; height: 26px; background: white; border-radius: 50%; transition: left 0.3s;"></div> </button> </div> <div style="display: flex; justify-content: space-between; margin-bottom: 15px; align-items: center;"> <span style="font-size: clamp(12px, 3.5vw, 14px);">Jump Boost</span> <button id="jumpToggle" style="background: #ff4444; border: none; border-radius: 15px; width: 60px; height: 30px; position: relative; cursor: pointer; min-height: 30px;"> <div style="position: absolute; top: 2px; left: 2px; width: 26px; height: 26px; background: white; border-radius: 50%; transition: left 0.3s;"></div> </button> </div> </div> <div style="margin-bottom: 15px;"> <h3 style="border-bottom: 1px solid #00ff00; padding-bottom: 5px; font-size: clamp(14px, 4vw, 16px);">Custom Scripts</h3> <textarea id="scriptInput" placeholder="Paste your script here..." style="width: 100%; height: 100px; background: rgba(255,255,255,0.1); color: white; border: 1px solid #00ff00; border-radius: 5px; padding: 10px; margin-bottom: 10px; resize: vertical; font-size: clamp(12px, 3.5vw, 14px); box-sizing: border-box;"></textarea> <div style="display: flex; justify-content: space-between; gap: 5px; flex-wrap: wrap;"> <button id="runScript" style="background: #00aa00; border: none; border-radius: 5px; color: white; padding: 10px; cursor: pointer; flex: 1; min-height: 44px; font-size: clamp(12px, 3.5vw, 14px);">Run</button> <button id="saveScript" style="background: #0088cc; border: none; border-radius: 5px; color: white; padding: 10px; cursor: pointer; flex: 1; min-height: 44px; font-size: clamp(12px, 3.5vw, 14px);">Save</button> <input type="text" id="scriptName" placeholder="Script name" style="background: rgba(255,255,255,0.1); color: white; border: 1px solid #00ff00; border-radius: 5px; padding: 10px; flex: 1; min-width: 100px; font-size: clamp(12px, 3.5vw, 14px); box-sizing: border-box;"> </div> </div> <div> <h3 style="border-bottom: 1px solid #00ff00; padding-bottom: 5px; font-size: clamp(14px, 4vw, 16px);">Saved Scripts</h3> <div id="savedScriptsList" style="max-height: 200px; overflow-y: auto;"> <!-- Saved scripts will be listed here --> </div> </div> </div> `; document.body.appendChild(floatingWindow); makeDraggable(floatingWindow); // 为所有按钮添加触摸事件支持 const addTouchSupport = (element, handler) => { element.addEventListener('click', handler); element.addEventListener('touchend', function(e) { e.preventDefault(); handler(); }); }; addTouchSupport(document.getElementById('speedToggle'), toggleSpeedBoost); addTouchSupport(document.getElementById('jumpToggle'), toggleJumpBoost); addTouchSupport(document.getElementById('runScript'), runCustomScript); addTouchSupport(document.getElementById('saveScript'), saveCustomScript); addTouchSupport(document.getElementById('minimizeBtn'), toggleMinimize); addTouchSupport(document.getElementById('closeBtn'), closeWindow); loadSavedScripts(); } function makeDraggable(element) { const header = element.querySelector('div'); let isDragging = false; let currentX, currentY, initialX, initialY, xOffset = 0, yOffset = 0; const dragStart = (clientX, clientY) => { initialX = clientX - xOffset; initialY = clientY - yOffset; isDragging = true; }; const dragEnd = () => { initialX = currentX; initialY = currentY; isDragging = false; }; const drag = (clientX, clientY) => { if (isDragging) { currentX = clientX - initialX; currentY = clientY - initialY; xOffset = currentX; yOffset = currentY; setTranslate(currentX, currentY, element); } }; const setTranslate = (xPos, yPos, el) => { el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0)`; }; // 鼠标事件 header.addEventListener("mousedown", (e) => { dragStart(e.clientX, e.clientY); }); document.addEventListener("mouseup", dragEnd); document.addEventListener("mousemove", (e) => { drag(e.clientX, e.clientY); }); // 触摸事件 header.addEventListener("touchstart", (e) => { e.preventDefault(); const touch = e.touches[0]; dragStart(touch.clientX, touch.clientY); }, { passive: false }); document.addEventListener("touchend", dragEnd); document.addEventListener("touchmove", (e) => { if (isDragging) { e.preventDefault(); const touch = e.touches[0]; drag(touch.clientX, touch.clientY); } }, { passive: false }); } // 其余函数保持不变(toggleSpeedBoost, applySpeedBoost, removeSpeedBoost, toggleJumpBoost, applyJumpBoost, removeJumpBoost, runCustomScript, saveCustomScript, loadSavedScripts, toggleMinimize, closeWindow, showNotification) function toggleSpeedBoost() { const toggle = document.getElementById('speedToggle'); const toggleCircle = toggle.querySelector('div'); if (!isSpeedBoostActive) { toggle.style.background = '#44ff44'; toggleCircle.style.left = '32px'; applySpeedBoost(); isSpeedBoostActive = true; showNotification('Speed Boost Activated'); } else { toggle.style.background = '#ff4444'; toggleCircle.style.left = '2px'; removeSpeedBoost(); isSpeedBoostActive = false; showNotification('Speed Boost Deactivated'); } } function applySpeedBoost() { const targetWalkSpeed = 115; Object.defineProperty(Object.prototype, 'walkSpeed', { get() { return this._walkSpeed || targetWalkSpeed; }, set(value) { this._walkSpeed = targetWalkSpeed; console.log('walkSpeed set to ' + this._walkSpeed); }, configurable: true }); Object.defineProperty(Object.prototype, 'flagWalkSpeed', { get() { return this._flagWalkSpeed || targetWalkSpeed; }, set(value) { this._flagWalkSpeed = targetWalkSpeed; console.log('flagWalkSpeed set to ' + this._flagWalkSpeed); }, configurable: true }); } function removeSpeedBoost() { delete Object.prototype.walkSpeed; delete Object.prototype.flagWalkSpeed; } function toggleJumpBoost() { const toggle = document.getElementById('jumpToggle'); const toggleCircle = toggle.querySelector('div'); if (!isJumpBoostActive) { toggle.style.background = '#44ff44'; toggleCircle.style.left = '32px'; applyJumpBoost(); isJumpBoostActive = true; showNotification('Jump Boost Activated'); } else { toggle.style.background = '#ff4444'; toggleCircle.style.left = '2px'; removeJumpBoost(); isJumpBoostActive = false; showNotification('Jump Boost Deactivated'); } } function applyJumpBoost() { const targetJumpForce = 20; Object.defineProperty(Object.prototype, 'jumpForce', { get() { return this._jumpForce || targetJumpForce; }, set(value) { this._jumpForce = targetJumpForce; console.log('jumpForce set to ' + this._jumpForce); }, configurable: true }); } function removeJumpBoost() { delete Object.prototype.jumpForce; } function runCustomScript() { const scriptCode = document.getElementById('scriptInput').value; if (scriptCode.trim()) { try { eval(scriptCode); showNotification('Custom script executed'); } catch (error) { showNotification('Error in script: ' + error.message, true); } } else { showNotification('Please enter a script', true); } } function saveCustomScript() { const scriptCode = document.getElementById('scriptInput').value; const scriptName = document.getElementById('scriptName').value; if (scriptCode.trim() && scriptName.trim()) { savedScripts[scriptName] = scriptCode; GM_setValue('savedScripts', savedScripts); loadSavedScripts(); showNotification('Script saved: ' + scriptName); document.getElementById('scriptName').value = ''; } else { showNotification('Please enter both script and name', true); } } function loadSavedScripts() { const savedScriptsList = document.getElementById('savedScriptsList'); savedScriptsList.innerHTML = ''; for (const name in savedScripts) { const scriptItem = document.createElement('div'); scriptItem.style.display = 'flex'; scriptItem.style.justifyContent = 'space-between'; scriptItem.style.alignItems = 'center'; scriptItem.style.marginBottom = '8px'; scriptItem.style.padding = '8px'; scriptItem.style.backgroundColor = 'rgba(255,255,255,0.1)'; scriptItem.style.borderRadius = '5px'; scriptItem.innerHTML = ` <span style="font-size: clamp(12px, 3.5vw, 14px);">${name}</span> <div> <button class="run-saved-script" data-name="${name}" style="background: #00aa00; border: none; border-radius: 5px; color: white; padding: 8px 12px; margin-right: 5px; cursor: pointer; font-size: clamp(11px, 3vw, 12px); min-height: 36px;">Run</button> <button class="delete-script" data-name="${name}" style="background: #ff4444; border: none; border-radius: 5px; color: white; padding: 8px 12px; cursor: pointer; font-size: clamp(11px, 3vw, 12px); min-height: 36px;">Delete</button> </div> `; savedScriptsList.appendChild(scriptItem); } // 为保存的脚本按钮添加触摸支持 document.querySelectorAll('.run-saved-script').forEach(button => { button.addEventListener('click', function() { const scriptName = this.getAttribute('data-name'); try { eval(savedScripts[scriptName]); showNotification('Script executed: ' + scriptName); } catch (error) { showNotification('Error in script: ' + error.message, true); } }); button.addEventListener('touchend', function(e) { e.preventDefault(); const scriptName = this.getAttribute('data-name'); try { eval(savedScripts[scriptName]); showNotification('Script executed: ' + scriptName); } catch (error) { showNotification('Error in script: ' + error.message, true); } }); }); document.querySelectorAll('.delete-script').forEach(button => { button.addEventListener('click', function() { const scriptName = this.getAttribute('data-name'); delete savedScripts[scriptName]; GM_setValue('savedScripts', savedScripts); loadSavedScripts(); showNotification('Script deleted: ' + scriptName); }); button.addEventListener('touchend', function(e) { e.preventDefault(); const scriptName = this.getAttribute('data-name'); delete savedScripts[scriptName]; GM_setValue('savedScripts', savedScripts); loadSavedScripts(); showNotification('Script deleted: ' + scriptName); }); }); } function toggleMinimize() { const content = document.getElementById('windowContent'); if (content.style.display === 'none') { content.style.display = 'block'; } else { content.style.display = 'none'; } } function closeWindow() { document.getElementById('greenToolsWindow').style.display = 'none'; showNotification('Green Tools minimized to system tray'); const reopenBtn = document.createElement('div'); reopenBtn.innerHTML = 'GT'; reopenBtn.style.position = 'fixed'; reopenBtn.style.bottom = '20px'; reopenBtn.style.right = '20px'; reopenBtn.style.width = '50px'; reopenBtn.style.height = '50px'; reopenBtn.style.backgroundColor = 'rgba(0, 100, 0, 0.9)'; reopenBtn.style.border = '2px solid #00ff00'; reopenBtn.style.borderRadius = '50%'; reopenBtn.style.display = 'flex'; reopenBtn.style.alignItems = 'center'; reopenBtn.style.justifyContent = 'center'; reopenBtn.style.color = 'white'; reopenBtn.style.fontSize = '16px'; reopenBtn.style.fontWeight = 'bold'; reopenBtn.style.cursor = 'pointer'; reopenBtn.style.zIndex = '10000'; reopenBtn.style.touchAction = 'manipulation'; reopenBtn.id = 'greenToolsReopen'; const reopenHandler = function() { document.getElementById('greenToolsWindow').style.display = 'block'; this.remove(); }; reopenBtn.addEventListener('click', reopenHandler); reopenBtn.addEventListener('touchend', function(e) { e.preventDefault(); reopenHandler.call(this); }); document.body.appendChild(reopenBtn); } function showNotification(message, isError = false) { const notification = document.createElement('div'); notification.textContent = message; notification.style.position = 'fixed'; notification.style.top = '20px'; notification.style.left = '50%'; notification.style.transform = 'translateX(-50%)'; notification.style.backgroundColor = isError ? 'rgba(255, 0, 0, 0.8)' : 'rgba(0, 255, 0, 0.8)'; notification.style.color = 'white'; notification.style.padding = '15px 25px'; notification.style.borderRadius = '8px'; notification.style.zIndex = '10001'; notification.style.fontSize = 'clamp(14px, 4vw, 16px)'; notification.style.fontWeight = 'bold'; notification.style.boxShadow = '0 0 15px rgba(0,0,0,0.5)'; notification.style.textAlign = 'center'; notification.style.maxWidth = '80vw'; document.body.appendChild(notification); setTimeout(() => { if (document.body.contains(notification)) { document.body.removeChild(notification); } }, 3000); } // 改进的初始化函数 function init() { console.log(` ____ _____ _ / ___| _ __ ___ ___ _ __ |_ _| ___ ___ | | ___ | | _ | '__| / _ \\ / _ \\ | '_ \\ | | / _ \\ / _ \\ | | / __| | |_| | | | | __/ | __/ | | | | | | | (_) | | (_) | | | \\__ \\ \\____| |_| \\___| \\___| |_| |_| |_| \\___/ \\___/ |_| |___/ Green Tools - Script Manager for Narrow One `); // 使用更可靠的初始化方法 const initInterval = setInterval(() => { if (document.body) { clearInterval(initInterval); createKeyOverlay(); initPasswordSystem(); // 确保密码输入框获得焦点 setTimeout(() => { const keyInput = document.getElementById('keyInput'); if (keyInput) { keyInput.focus(); } }, 1000); } }, 100); // 10秒后停止检查 setTimeout(() => { clearInterval(initInterval); }, 10000); } // 启动脚本 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { setTimeout(init, 100); } })();