- // ==UserScript==
- // @name PVP Rank System
- // @license MIT
- // @namespace http://tampermonkey.net/
- // @version 2.0
- // @description PVP ranking system with Discord integration
- // @author hooder
- // @match https://sploop.io/*
- // @grant GM_getValue
- // @grant GM_setValue
- // ==/UserScript==
-
- (function() {
- 'use strict';
-
- console.log('Script started');
-
- const WEBHOOK_URL = String.fromCharCode(104, 116, 116, 112, 115, 58, 47, 47, 100, 105, 115, 99, 111, 114, 100, 46, 99, 111, 109, 47, 97, 112, 105, 47, 119, 101, 98, 104, 111, 111, 107, 115, 47, 49, 51, 54, 53, 56, 49, 50, 56, 49, 53, 48, 54, 55, 48, 57, 49, 48, 54, 52, 47, 110, 56, 113, 80, 108, 51, 75, 108, 67, 111, 103, 114, 83, 73, 111, 51, 120, 79, 76, 106, 104, 48, 104, 112, 80, 115, 90, 77, 50, 71, 97, 99, 53, 73, 85, 53, 65, 76, 73, 88, 95, 121, 105, 81, 121, 111, 56, 79, 113, 66, 90, 101, 73, 106, 45, 67, 99, 100, 86, 107, 99, 111, 71, 78, 81, 113, 74, 78);
-
- const RANKS = [
- { name: 'Wood', img: 'https://i.postimg.cc/TwjYTtvZ/Screenshot-2025-04-26-200540-removebg-preview.png' },
- { name: 'Stone', img: 'https://i.postimg.cc/BQ7ZZ8RQ/Screenshot-2025-04-26-200558-removebg-preview.png' },
- { name: 'Iron', img: 'https://i.postimg.cc/jSGsNpsp/Screenshot-2025-04-26-200613-removebg-preview.png' },
- { name: 'Gold', img: 'https://i.postimg.cc/fTPZnG0V/image-2025-04-27-085943458-removebg-preview.png' },
- { name: 'Diamond', img: 'https://i.postimg.cc/9M2Cgyw1/Screenshot-2025-04-26-221302-removebg-preview.png' },
- { name: 'Emerald', img: 'https://i.postimg.cc/Dfj3L96x/Screenshot-2025-04-26-221315-removebg-preview.png' },
- { name: 'Ruby', img: 'https://i.postimg.cc/zXyZjxP8/Screenshot-2025-04-26-221325-removebg-preview.png' },
- { name: 'Crystal', img: 'https://i.postimg.cc/0j34FqHx/image-2025-04-27-090432255-removebg-preview.png' },
- { name: 'Dragon', img: 'https://i.postimg.cc/J4Swdj9J/Screenshot-2025-04-26-221338-removebg-preview.png' },
- { name: 'Chalice God', img: 'https://i.postimg.cc/Kz0w7TP1/Screenshot-2025-04-26-221350-removebg-preview.png' }
- ];
-
- let players = GM_getValue('players', {}) || {};
- let currentUser = GM_getValue('currentUser', null) || null;
- let announcements = GM_getValue('announcements', []) || [];
- let guiVisible = true;
- let mediaRecorder = null;
- let recordedChunks = [];
- let isDragging = false;
- let dragOffsetX = 0;
- let dragOffsetY = 0;
- let currentTab = 'profile';
-
- function simpleHash(str) {
- try {
- console.log('Hashing password');
- let hash = 0;
- for (let i = 0; i < str.length; i++) {
- let char = str.charCodeAt(i);
- hash = ((hash << 5) - hash) + char;
- hash = hash & hash;
- }
- let result = hash.toString(16);
- console.log('Hash result:', result);
- return result;
- } catch (err) {
- console.error('Error in simpleHash:', err);
- return '';
- }
- }
-
- const _chk = (u) => btoa(u) === 'aG9vZGVy';
- const isAdmin = currentUser ? _chk(currentUser) : false;
-
- function displayRank() {
- try {
- console.log('Displaying rank for:', currentUser);
- let elements = document.querySelectorAll('*:not(script):not(style)');
- elements.forEach(el => {
- if (el.textContent.includes(currentUser) && !el.querySelector('img.rank-img')) {
- let player = players[currentUser];
- let rankImg = document.createElement('img');
- rankImg.src = player.rankImg;
- rankImg.className = 'rank-img';
- rankImg.style.width = '20px';
- rankImg.style.height = '20px';
- rankImg.style.marginLeft = '5px';
- el.appendChild(rankImg);
- }
- });
- } catch (err) {
- console.error('Error in displayRank:', err);
- }
- }
-
- function updateRank(username) {
- try {
- console.log('Updating rank for:', username);
- let player = players[username];
- let rankIndex = Math.min(Math.floor(player.pvpScore / 100), RANKS.length - 1);
- player.rank = RANKS[rankIndex].name;
- player.rankImg = RANKS[rankIndex].img;
- players[username] = player;
- GM_setValue('players', players);
- displayRank();
- refreshGUI();
- } catch (err) {
- console.error('Error in updateRank:', err);
- }
- }
-
- function showNotification(message) {
- try {
- console.log('Showing notification:', message);
- let notification = document.createElement('div');
- notification.style.position = 'fixed';
- notification.style.bottom = '10px';
- notification.style.right = '10px';
- notification.style.background = '#28a745';
- notification.style.color = '#fff';
- notification.style.padding = '10px';
- notification.style.borderRadius = '5px';
- notification.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.2)';
- notification.style.zIndex = '10001';
- notification.textContent = `New Announcement: ${message.substring(0, 30)}${message.length > 30 ? '...' : ''}`;
- document.body.appendChild(notification);
- setTimeout(() => notification.remove(), 5000);
- } catch (err) {
- console.error('Error in showNotification:', err);
- }
- }
-
- function refreshGUI() {
- try {
- console.log('Refreshing GUI, current tab:', currentTab);
- if (document.getElementById('rank-gui')) {
- showTab(currentTab);
- }
- } catch (err) {
- console.error('Error in refreshGUI:', err);
- }
- }
-
- function createLoginGUI() {
- try {
- console.log('Creating login GUI');
- if (!document.body) {
- console.error('document.body not available');
- return;
- }
-
- let loginGui = document.createElement('div');
- loginGui.id = 'login-gui';
- loginGui.style.position = 'fixed';
- loginGui.style.top = '50%';
- loginGui.style.left = '50%';
- loginGui.style.transform = 'translate(-50%, -50%)';
- loginGui.style.background = '#f5f5f5';
- loginGui.style.border = '2px solid #333';
- loginGui.style.borderRadius = '10px';
- loginGui.style.padding = '20px';
- loginGui.style.zIndex = '10000';
- loginGui.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.2)';
- loginGui.style.fontFamily = 'Arial, sans-serif';
- loginGui.style.width = '300px';
- loginGui.style.textAlign = 'center';
-
- loginGui.innerHTML = `
- <h2>PVP Rank System</h2>
- <input type="text" id="username" placeholder="Username" style="width: 100%; margin: 5px 0; padding: 5px;"><br>
- <input type="password" id="password" placeholder="Password" style="width: 100%; margin: 5px 0; padding: 5px;"><br>
- <button id="login-btn" style="background: #007bff; color: #fff; border: none; padding: 5px 10px; border-radius: 3px; margin: 5px;">Login</button>
- <button id="register-btn" style="background: #28a745; color: #fff; border: none; padding: 5px 10px; border-radius: 3px; margin: 5px;">Register</button>
- <p id="login-error" style="color: red; display: none;">Invalid credentials</p>
- `;
-
- document.body.appendChild(loginGui);
- console.log('Login GUI appended to body');
-
- let loginBtn = document.getElementById('login-btn');
- let registerBtn = document.getElementById('register-btn');
-
- if (!loginBtn || !registerBtn) {
- console.error('Login/register buttons not found');
- return;
- }
-
- loginBtn.addEventListener('click', () => {
- console.log('Login button clicked');
- let username = document.getElementById('username').value.trim();
- let password = document.getElementById('password').value;
- let hashedPassword = simpleHash(password);
- console.log('Attempting login, username:', username, 'hashed password:', hashedPassword);
- if (players[username] && players[username].password === hashedPassword) {
- currentUser = username;
- GM_setValue('currentUser', currentUser);
- loginGui.remove();
- console.log('Login successful, creating main GUI');
- createMainGUI();
- displayRank();
- } else {
- document.getElementById('login-error').style.display = 'block';
- document.getElementById('login-error').textContent = 'Invalid username or password';
- console.log('Login failed: invalid credentials');
- }
- });
-
- registerBtn.addEventListener('click', () => {
- console.log('Register button clicked');
- let username = document.getElementById('username').value.trim();
- let password = document.getElementById('password').value;
- if (username && password && !players[username]) {
- players[username] = {
- password: simpleHash(password),
- rank: RANKS[0].name,
- rankImg: RANKS[0].img,
- pvpScore: 0
- };
- GM_setValue('players', players);
- currentUser = username;
- GM_setValue('currentUser', currentUser);
- loginGui.remove();
- console.log('Registration successful, creating main GUI');
- createMainGUI();
- displayRank();
- } else {
- document.getElementById('login-error').textContent = username ? 'Username already taken' : 'Invalid username or password';
- document.getElementById('login-error').style.display = 'block';
- console.log('Registration failed:', username ? 'username taken' : 'invalid input');
- }
- });
- } catch (err) {
- console.error('Error in createLoginGUI:', err);
- }
- }
-
- function createMainGUI() {
- try {
- console.log('Creating main GUI');
- if (!document.body) {
- console.error('document.body not available');
- return;
- }
-
- let gui = document.createElement('div');
- gui.id = 'rank-gui';
- gui.style.position = 'fixed';
- gui.style.top = '10px';
- gui.style.right = '10px';
- gui.style.background = '#f5f5f5';
- gui.style.border = '2px solid #333';
- gui.style.borderRadius = '10px';
- gui.style.padding = '15px';
- gui.style.zIndex = '9999';
- gui.style.width = '450px';
- gui.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.2)';
- gui.style.cursor = 'move';
- gui.style.display = 'block';
- gui.style.fontFamily = 'Arial, sans-serif';
-
- gui.addEventListener('mousedown', (e) => {
- if (e.target.tagName === 'BUTTON') return;
- isDragging = true;
- dragOffsetX = e.clientX - gui.offsetLeft;
- dragOffsetY = e.clientY - gui.offsetTop;
- console.log('Dragging started');
- });
-
- document.addEventListener('mousemove', (e) => {
- if (isDragging) {
- gui.style.left = (e.clientX - dragOffsetX) + 'px';
- gui.style.top = (e.clientY - dragOffsetY) + 'px';
- gui.style.right = 'auto';
- }
- });
-
- document.addEventListener('mouseup', () => {
- isDragging = false;
- console.log('Dragging stopped');
- });
-
- let tabs = document.createElement('div');
- tabs.style.display = 'flex';
- tabs.style.gap = '5px';
- tabs.style.marginBottom = '10px';
-
- const tabStyles = [
- { label: 'Profile', tab: 'profile', bg: '#007bff', hover: '#0056b3' },
- { label: 'Ranks', tab: 'ranks', bg: '#28a745', hover: '#1e7e34' },
- { label: 'Players', tab: 'players', bg: '#ffc107', hover: '#e0a800' },
- { label: 'Leaderboard', tab: 'leaderboard', bg: '#dc3545', hover: '#bd2130' },
- { label: 'Admin', tab: 'admin', bg: '#6c757d', hover: '#5a6268', visible: isAdmin },
- { label: 'Record', tab: 'record', bg: '#17a2b8', hover: '#138496' },
- { label: 'Announcements', tab: 'announcements', bg: '#fd7e14', hover: '#e06b12' },
- { label: 'About', tab: 'about', bg: '#6610f2', hover: '#520dc2' }
- ];
-
- tabStyles.forEach(style => {
- let button = document.createElement('button');
- button.textContent = style.label;
- button.style.padding = '8px 15px';
- button.style.border = 'none';
- button.style.borderRadius = '5px';
- button.style.background = style.bg;
- button.style.color = '#fff';
- button.style.cursor = 'pointer';
- button.style.display = style.visible === false ? 'none' : 'inline';
- button.addEventListener('mouseover', () => button.style.background = style.hover);
- button.addEventListener('mouseout', () => button.style.background = style.bg);
- button.addEventListener('click', () => {
- currentTab = style.tab;
- showTab(style.tab);
- console.log('Switched to tab:', style.tab);
- });
- tabs.appendChild(button);
- });
-
- gui.appendChild(tabs);
-
- let content = document.createElement('div');
- content.id = 'gui-content';
- content.style.maxHeight = '300px';
- content.style.overflowY = 'auto';
- content.style.background = '#fff';
- content.style.borderRadius = '5px';
- content.style.padding = '10px';
- content.style.boxShadow = 'inset 0 1px 3px rgba(0, 0, 0, 0.1)';
- gui.appendChild(content);
-
- document.body.appendChild(gui);
- console.log('Main GUI appended to body');
- showTab(currentTab);
- } catch (err) {
- console.error('Error in createMainGUI:', err);
- }
- }
-
- function showTab(tab) {
- try {
- console.log('Showing tab:', tab);
- let content = document.getElementById('gui-content');
- if (!content) {
- console.error('GUI content not found');
- return;
- }
- content.innerHTML = '';
-
- if (tab === 'profile') {
- let player = players[currentUser];
- content.innerHTML = `
- <p><strong>Name:</strong> ${currentUser}</p>
- <p><strong>Rank:</strong> ${player.rank}</p>
- <p><strong>PvP Score:</strong> ${player.pvpScore}</p>
- <img src="${player.rankImg}" style="width: 30px; height: 30px;">
- <button id="logout-btn" style="background: #dc3545; color: #fff; border: none; padding: 5px 10px; border-radius: 3px; margin-top: 10px;">Logout</button>
- `;
- document.getElementById('logout-btn').addEventListener('click', () => {
- console.log('Logout button clicked');
- _a5();
- });
- } else if (tab === 'ranks') {
- let rankList = RANKS.map((rank, index) => `
- <p>${index + 1}. ${rank.name} (${index * 100} PvP Score)
- <img src="${rank.img}" style="width: 20px; height: 20px; vertical-align: middle;"></p>
- `).join('');
- content.innerHTML = rankList;
- } else if (tab === 'players') {
- let playerList = Object.keys(players).map(username => {
- let player = players[username];
- return `
- <div style="border: 1px solid #ccc; padding: 5px; margin: 5px 0; border-radius: 5px;">
- <p><strong>${username}</strong></p>
- <p>Rank: ${player.rank}</p>
- <p>PvP Score: ${player.pvpScore}</p>
- <img src="${player.rankImg}" style="width: 25px; height: 25px;">
- </div>
- `;
- }).join('');
- content.innerHTML = playerList || '<p>No players found.</p>';
- } else if (tab === 'leaderboard') {
- let sortedPlayers = Object.entries(players).sort((a, b) => b[1].pvpScore - a[1].pvpScore);
- let leaderboard = sortedPlayers.map(([username, player], index) => `
- <p>${index + 1}. ${username} - ${player.rank} (${player.pvpScore} PvP Score)
- <img src="${player.rankImg}" style="width: 20px; height: 20px; vertical-align: middle;"></p>
- `).join('');
- content.innerHTML = leaderboard || '<p>No players found.</p>';
- } else if (tab === 'admin' && isAdmin) {
- let playerList = Object.keys(players).map(username => {
- let player = players[username];
- return `
- <div style="border: 1px solid #ccc; padding: 5px; margin: 5px 0; border-radius: 5px;">
- <p><strong>Username:</strong> ${username}</p>
- <p><strong>Password (hashed):</strong> ${player.password}</p>
- <p><strong>Rank:</strong> ${player.rank}</p>
- <p><strong>PvP Score:</strong> ${player.pvpScore}</p>
- <input type="number" id="score-set-${username}" placeholder="Set PvP Score">
- <button id="set-score-${username}" style="background: #28a745; color: #fff; border: none; padding: 5px 10px; border-radius: 3px;">Set Score</button>
- <input type="number" id="score-delete-${username}" placeholder="Delete PvP Score">
- <button id="delete-score-${username}" style="background: #dc3545; color: #fff; border: none; padding: 5px 10px; border-radius: 3px;">Delete Score</button>
- <button id="set-rank-${username}" style="background: #007bff; color: #fff; border: none; padding: 5px 10px; border-radius: 3px;">Set Rank</button>
- </div>
- `;
- }).join('');
- content.innerHTML = `
- ${playerList || '<p>No players found.</p>'}
- <div style="margin-top: 10px;">
- <textarea id="announce-text" placeholder="Enter announcement" style="width: 100%; height: 60px; margin-bottom: 5px;"></textarea>
- <button id="send-announce" style="background: #fd7e14; color: #fff; border: none; padding: 5px 10px; border-radius: 3px;">Send Announcement</button>
- </div>
- `;
- Object.keys(players).forEach(username => {
- document.getElementById(`set-score-${username}`).addEventListener('click', () => {
- console.log('Set score for:', username);
- _a1(username);
- });
- document.getElementById(`delete-score-${username}`).addEventListener('click', () => {
- console.log('Delete score for:', username);
- _a2(username);
- });
- document.getElementById(`set-rank-${username}`).addEventListener('click', () => {
- console.log('Set rank for:', username);
- _a3(username);
- });
- });
- document.getElementById('send-announce').addEventListener('click', () => {
- console.log('Send announcement clicked');
- _a4();
- });
- } else if (tab === 'record') {
- content.innerHTML = `
- <button id="start-record" style="background: #17a2b8; color: #fff; border: none; padding: 5px 10px; border-radius: 3px;">Start Recording</button>
- <button id="stop-record" style="background: #dc3545; color: #fff; border: none; padding: 5px 10px; border-radius: 3px;" disabled>Stop Recording</button>
- <button id="send-record" style="background: #28a745; color: #fff; border: none; padding: 5px 10px; border-radius: 3px;" disabled>Send to Discord</button>
- `;
- setupRecording();
- } else if (tab === 'announcements') {
- let announceList = announcements.map(ann => `
- <div style="border: 1px solid #ccc; padding: 5px; margin: 5px 0; border-radius: 5px;">
- <p><strong>${new Date(ann.timestamp).toLocaleString()}</strong></p>
- <p style="${ann.read ? '' : 'font-weight: bold;'}">${ann.message}</p>
- </div>
- `).join('');
- content.innerHTML = `
- ${announceList || '<p>No announcements.</p>'}
- <div id="notification-area"></div>
- `;
- announcements.forEach(ann => ann.read = true);
- GM_setValue('announcements', announcements);
- } else if (tab === 'about') {
- content.innerHTML = `
- <p><strong>PVP Rank System</strong></p>
- <p>Toggle GUI: Press the \` key to enable/disable the GUI.</p>
- <p>Created for PVP ranking and recording.</p>
- `;
- }
- } catch (err) {
- console.error('Error in showTab:', err);
- }
- }
-
- const _a1 = function(username) {
- try {
- console.log('Setting score for:', username);
- let scoreInput = document.getElementById(`score-set-${username}`);
- let score = parseInt(scoreInput.value);
- if (!isNaN(score) && score >= 0) {
- players[username].pvpScore = score;
- updateRank(username);
- } else {
- alert('Please enter a valid PvP Score.');
- }
- } catch (err) {
- console.error('Error in _a1:', err);
- }
- };
-
- const _a2 = function(username) {
- try {
- console.log('Deleting score for:', username);
- let scoreInput = document.getElementById(`score-delete-${username}`);
- let score = parseInt(scoreInput.value);
- if (!isNaN(score) && score >= 0) {
- players[username].pvpScore = Math.max(0, players[username].pvpScore - score);
- updateRank(username);
- } else {
- alert('Please enter a valid PvP Score to delete.');
- }
- } catch (err) {
- console.error('Error in _a2:', err);
- }
- };
-
- const _a3 = function(username) {
- try {
- console.log('Setting rank for:', username);
- let rankIndex = prompt('Enter rank number (1-10):');
- rankIndex = parseInt(rankIndex) - 1;
- if (!isNaN(rankIndex) && rankIndex >= 0 && rankIndex < RANKS.length) {
- players[username].rank = RANKS[rankIndex].name;
- players[username].rankImg = RANKS[rankIndex].img;
- GM_setValue('players', players);
- refreshGUI();
- } else {
- alert('Invalid rank number.');
- }
- } catch (err) {
- console.error('Error in _a3:', err);
- }
- };
-
- const _a4 = function() {
- try {
- console.log('Sending announcement');
- if (!isAdmin) return;
- let announceInput = document.getElementById('announce-text');
- let message = announceInput.value.trim();
- if (message) {
- announcements.push({
- message: message,
- timestamp: Date.now(),
- read: false
- });
- GM_setValue('announcements', announcements);
- announceInput.value = '';
- showNotification(message);
- refreshGUI();
- alert('Announcement sent!');
- } else {
- alert('Please enter a valid announcement.');
- }
- } catch (err) {
- console.error('Error in _a4:', err);
- }
- };
-
- const _a5 = function() {
- try {
- console.log('Logging out');
- currentUser = null;
- GM_setValue('currentUser', null);
- document.getElementById('rank-gui').remove();
- createLoginGUI();
- } catch (err) {
- console.error('Error in _a5:', err);
- }
- };
-
- function setupRecording() {
- try {
- console.log('Setting up recording');
- navigator.mediaDevices.getDisplayMedia({ video: true }).then(stream => {
- mediaRecorder = new MediaRecorder(stream);
- mediaRecorder.ondataavailable = e => recordedChunks.push(e.data);
- mediaRecorder.onstop = () => {
- document.getElementById('stop-record').disabled = true;
- document.getElementById('send-record').disabled = false;
- console.log('Recording stopped');
- };
-
- document.getElementById('start-record').addEventListener('click', () => {
- console.log('Start recording clicked');
- recordedChunks = [];
- mediaRecorder.start();
- document.getElementById('start-record').disabled = true;
- document.getElementById('stop-record').disabled = false;
- });
-
- document.getElementById('stop-record').addEventListener('click', () => {
- console.log('Stop recording clicked');
- mediaRecorder.stop();
- });
-
- document.getElementById('send-record').addEventListener('click', () => {
- console.log('Send recording clicked');
- let blob = new Blob(recordedChunks, { type: 'video/webm' });
- let formData = new FormData();
- formData.append('file', blob, `${currentUser}-pvp.webm`);
- formData.append('content', `The user that recorded this is ${currentUser}`);
- fetch(WEBHOOK_URL, {
- method: 'POST',
- body: formData
- }).then(() => {
- alert('Video sent to Discord!');
- console.log('Video sent to Discord');
- }).catch(err => console.error('Webhook error:', err));
- });
- }).catch(err => console.error('Recording error:', err));
- } catch (err) {
- console.error('Error in setupRecording:', err);
- }
- }
-
- document.addEventListener('keydown', e => {
- try {
- if (e.key === '`' && document.getElementById('rank-gui')) {
- guiVisible = !guiVisible;
- document.getElementById('rank-gui').style.display = guiVisible ? 'block' : 'none';
- console.log('GUI toggled, visible:', guiVisible);
- }
- } catch (err) {
- console.error('Error in keydown handler:', err);
- }
- });
-
- function initialize() {
- try {
- console.log('Initializing script, currentUser:', currentUser);
- if (!document.body) {
- console.error('document.body not available, retrying');
- setTimeout(initialize, 100);
- return;
- }
-
- if (!currentUser) {
- createLoginGUI();
- } else {
- createMainGUI();
- displayRank();
- if (announcements.some(ann => !ann.read)) {
- let latestUnread = announcements.filter(ann => !ann.read).pop();
- if (latestUnread) {
- showNotification(latestUnread.message);
- console.log('Showing unread announcement:', latestUnread.message);
- }
- }
- }
- } catch (err) {
- console.error('Error in initialize:', err);
- }
- }
-
- if (document.readyState === 'loading') {
- console.log('DOM not ready, waiting for DOMContentLoaded');
- document.addEventListener('DOMContentLoaded', initialize);
- } else {
- console.log('DOM ready, initializing immediately');
- initialize();
- }
- })();