您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Load saves for whatbeatsrock.com with pause functionality, adjustable wait time, file-based save selection, improved UI with padding, and edge-only dragging with scrollable middle
// ==UserScript== // @name WhatBeatsRock Save Loader // @namespace http://violentmonkey.net/ // @version 3.0 // @description Load saves for whatbeatsrock.com with pause functionality, adjustable wait time, file-based save selection, improved UI with padding, and edge-only dragging with scrollable middle // @author JoTheStupid // @match https://www.whatbeatsrock.com/* // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; let paused = false; let saveEntries = []; let index = 0; let isDragging = false; let dragStartX, dragStartY, startX, startY; // UI Styles const buttonStyle = ` padding: 8px 16px; margin-top: 10px; background-color: #4CAF50; border: 2px solid #333; color: white; cursor: pointer; font-size: 14px; border-radius: 5px; text-align: center; `; const pauseButtonStyle = ` padding: 8px 16px; margin-top: 10px; background-color: #f44336; border: 2px solid #333; color: white; cursor: pointer; font-size: 14px; border-radius: 5px; text-align: center; `; const containerStyle = ` padding: 10px; background-color: white; border: 2px solid black; border-radius: 10px; position: fixed; top: 10px; right: 10px; width: 320px; height: 500px; z-index: 1000; resize: both; overflow: auto; min-width: 200px; min-height: 200px; `; const edgeThreshold = 10; // The distance from the edge in pixels to allow dragging // Create a container for input elements let container = document.createElement('div'); container.style.cssText = containerStyle; document.body.appendChild(container); // Handle dragging the container (only from edges) container.addEventListener('mousedown', function (e) { const rect = container.getBoundingClientRect(); const isEdge = e.clientX - rect.left < edgeThreshold || rect.right - e.clientX < edgeThreshold || e.clientY - rect.top < edgeThreshold || rect.bottom - e.clientY < edgeThreshold; if (isEdge) { isDragging = true; dragStartX = e.clientX; dragStartY = e.clientY; startX = container.offsetLeft; startY = container.offsetTop; e.preventDefault(); } }); document.addEventListener('mousemove', function (e) { if (isDragging) { let offsetX = e.clientX - dragStartX; let offsetY = e.clientY - dragStartY; container.style.left = startX + offsetX + 'px'; container.style.top = startY + offsetY + 'px'; } }); document.addEventListener('mouseup', function () { isDragging = false; }); // Create a file input for save file upload let fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.accept = '.txt'; fileInput.style.width = '100%'; fileInput.style.marginBottom = '10px'; container.appendChild(fileInput); // Create a textbox for input let inputBox = document.createElement('textarea'); inputBox.style.width = '100%'; inputBox.style.height = '100px'; inputBox.style.padding = '5px'; inputBox.style.border = '1px solid #ccc'; inputBox.style.borderRadius = '5px'; inputBox.style.marginBottom = '10px'; container.appendChild(inputBox); // Create a button to apply the save let enterSaveButton = document.createElement('button'); enterSaveButton.innerHTML = 'Enter Save'; enterSaveButton.style.cssText += buttonStyle; container.appendChild(enterSaveButton); // Create a pause/resume button let pauseButton = document.createElement('button'); pauseButton.innerHTML = 'Pause'; pauseButton.style.cssText += pauseButtonStyle; container.appendChild(pauseButton); pauseButton.addEventListener('click', () => { paused = !paused; pauseButton.innerHTML = paused ? 'Resume' : 'Pause'; pauseButton.style.backgroundColor = paused ? '#f44336' : '#4CAF50'; if (!paused) { processNextEntry(); } }); // Create a label for the slider let sliderLabel = document.createElement('label'); sliderLabel.innerHTML = 'Wait Time (ms):'; container.appendChild(sliderLabel); // Create a slider for wait time let waitTimeSlider = document.createElement('input'); waitTimeSlider.type = 'range'; waitTimeSlider.min = '100'; waitTimeSlider.max = '3000'; waitTimeSlider.value = '1000'; waitTimeSlider.style.width = '100%'; waitTimeSlider.style.marginBottom = '10px'; container.appendChild(waitTimeSlider); // Display the current wait time let waitTimeDisplay = document.createElement('div'); waitTimeDisplay.innerHTML = `Current wait time: ${waitTimeSlider.value} ms`; waitTimeDisplay.style.marginBottom = '10px'; container.appendChild(waitTimeDisplay); // Create a div to show color-coded save options let saveListContainer = document.createElement('div'); saveListContainer.style.width = '100%'; saveListContainer.style.height = '150px'; // Set height and make it scrollable saveListContainer.style.overflowY = 'auto'; // Enable vertical scrolling for the save list saveListContainer.style.border = '1px solid #ccc'; saveListContainer.style.borderRadius = '5px'; container.appendChild(saveListContainer); // Color cycle for the saves const colors = ['red', 'orange', 'yellow', 'blue', 'purple']; // Handle file reading and populate the saveList with color-coded saves fileInput.addEventListener('change', (event) => { const file = event.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = function(e) { const contents = e.target.result; const saves = contents.split('\n').map(save => save.trim()).filter(save => save !== ''); // Clear previous saves saveListContainer.innerHTML = ''; // Populate the save list with color-coded clickable divs saves.forEach((save, idx) => { let saveItem = document.createElement('div'); saveItem.textContent = save; saveItem.style.cursor = 'pointer'; saveItem.style.padding = '5px'; saveItem.style.border = '1px solid black'; saveItem.style.marginBottom = '5px'; saveItem.style.backgroundColor = colors[idx % colors.length]; // Alternate colors // Click to insert the save into the input box saveItem.addEventListener('click', () => { inputBox.value = save; }); saveListContainer.appendChild(saveItem); }); console.log('Saves loaded:', saves); }; reader.readAsText(file); } }); // Update the wait time display as the slider is moved waitTimeSlider.addEventListener('input', () => { waitTimeDisplay.innerHTML = `Current wait time: ${waitTimeSlider.value} ms`; }); // Function to find the Next button function findNextButton() { return document.querySelector('button.py-4.px-8.border.border-1-black.text-lg'); } // Function to simulate typing and clicking function simulateInput(input, callback) { if (paused) return; console.log(`Simulating input: ${input}`); let inputField = document.querySelector('.pl-4.py-4.text-lg.border.border-1-black'); let submitButton = document.querySelector('.p-4.border.border-1-black.text-lg.bg-green-200, .p-4.border.border-1-black.text-lg.text-gray-400'); if (inputField && submitButton) { inputField.focus(); Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set.call(inputField, input); let inputEvent = new Event('input', { bubbles: true }); let changeEvent = new Event('change', { bubbles: true }); inputField.dispatchEvent(inputEvent); inputField.dispatchEvent(changeEvent); setTimeout(() => { submitButton.click(); setTimeout(() => { let nextButton = findNextButton(); if (nextButton) { nextButton.click(); // Click the next button setTimeout(callback, parseInt(waitTimeSlider.value)); } else { console.log('Next button not found, retrying...'); setTimeout(() => simulateInput(input, callback), parseInt(waitTimeSlider.value)); // Retry if the next button is not found } }, parseInt(waitTimeSlider.value)); }, parseInt(waitTimeSlider.value)); } else { console.log('Input field or submit button not found, retrying...'); setTimeout(() => simulateInput(input, callback), parseInt(waitTimeSlider.value)); } } // Function to enter the save from the input box and start processing it function enterSave() { let saveText = inputBox.value.trim(); if (!saveText) { alert('Please enter a save'); console.log('No save text entered.'); return; } saveEntries = saveText.split('🤜').map(entry => entry.trim()).reverse(); index = 0; processNextEntry(); } function processNextEntry() { if (paused) return; if (index < saveEntries.length) { let currentInput = checkTextBoxForCurrentInput(); let currentIndex = saveEntries.findIndex(entry => entry.toLowerCase() === currentInput.toLowerCase()); if (currentIndex !== -1 && currentIndex + 1 < saveEntries.length) { console.log(`Current input is "${currentInput}". Inputting next entry: ${saveEntries[currentIndex + 1]}`); simulateInput(saveEntries[currentIndex + 1], () => { index = currentIndex + 2; processNextEntry(); }); } else { console.log(`Current input "${currentInput}" does not match any expected input. Retrying...`); setTimeout(processNextEntry, parseInt(waitTimeSlider.value)); } } else { console.log('All entries processed.'); } } function checkTextBoxForCurrentInput() { let currentInputElement = document.querySelector('.text-2xl.text-center'); if (currentInputElement) { let currentInput = currentInputElement.textContent.trim(); if (currentInput.endsWith('?')) { currentInput = currentInput.slice(0, -1); } return currentInput; } return null; } // Add the Enter Save button click event enterSaveButton.addEventListener('click', () => { console.log('Enter Save button clicked.'); enterSave(); }); })();