// ==UserScript== // @name 擂台脚本 // @namespace 简单易改的脚本,无bug // @version 1.2.0 // @description 简单易改的脚本,无Bug // @author EC // @match https://game.elfive.cn:91/wtfgame/ // @match https://wtf.haven.chat/ // @grant none // @run-at document-start // ==/UserScript== // 定义全局变量 var number = 0, // 用于控制消息处理的次数 players = [], ws, of = "关",// WebSocket实例 hookmessage, hooksend, // 用于存储原始的WebSocket send方法和onmessage事件 me = [{ // 存储当前玩家的信息 name: "", uuid: 0, x: 0, y: 0 }], ren = [], // 存储其他玩家的信息 player1 = { name: "", uuid: 0 }, player2 = { name: "", uuid: 0 }, score1 = 0, score2 = 0, start = 0 // 拦截原生WebSocket构造函数 var hook = window.WebSocket; window.WebSocket = function(protocols) { ws = new hook(protocols); // 创建一个新的WebSocket实例 // 保存原生的send方法 hooksend = ws.send; // 拦截WebSocket的send方法 ws.send = function(data) { var datas = jie(data); // 解密发送的数据 j3(datas); // 处理发送的数据(例如更新玩家信息) hooksend.call(ws, data); // 调用原生的send方法发送数据 }; // 监听WebSocket的message事件 ws.addEventListener('message', function(event) { if (number < 2) { // 限制消息处理的次数 number++; } if (number == 1) { hookmessage = ws.onmessage; // 保存原始的onmessage事件处理函数 } let r = qc.wtf.GameManager.instance.channel; if(r > 0 && of == "开"){ send(`{"k":"msg","v":{"msg":"/room py"}}`); } ws.onmessage = function(e) { var datas = jie(e.data); // 解密收到的消息 f(datas); // 处理消息(调用对应的事件处理函数) hookmessage(e); // 调用原始的onmessage事件处理函数 }; }); // 监听WebSocket的close事件 ws.addEventListener('close', function(event) { alert("断开连接"); // 提示用户连接已断开 }); return ws; // 返回新的WebSocket实例 }; // 自定义发送函数(封装了加密和调用原生send方法) function send(message) { let data = jia(message); // 加密消息 hooksend.call(ws, data); // 调用原生的send方法发送加密后的消息 } // 定义事件处理函数 const eventHandlers = { move(e) { // 玩家移动事件 let json = JSON.parse(e); a(arr = j(e)); // 更新玩家位置 if(json.v.uuid == player1.uuid || json.v.uuid == player2.uuid){ if(json.v.y > -300){ send(`{"k":"move","v":{"t":"throw","uuid":${player1.uuid},"dir":1,"x":510,"y":-350}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player2.uuid},"dir":1,"x":950,"y":-350}}`); } } if (start) { if (e.includes('throw')) { if (json.v.uuid == player1.uuid && json.v.target == player2.uuid) { score1++; send(`{"k":"msg","v":{"msg":"${player1.name} ${score1}:${score2} ${player2.name}"}}`); } else if (json.v.uuid == player2.uuid && json.v.target == player1.uuid) { score2++; send(`{"k":"msg","v":{"msg":"${player1.name} ${score1}:${score2} ${player2.name}"}}`); } } if (score1 == 10) { send(`{"k":"msg","v":{"msg":"${player1.name}获胜"}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player1.uuid},"dir":1,"x":0,"y":0}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player2.uuid},"dir":1,"x":0,"y":0}}`); reset(); settime(1) } else if (score2 == 10) { send(`{"k":"msg","v":{"msg":"${player2.name}获胜"}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player1.uuid},"dir":1,"x":0,"y":0}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player2.uuid},"dir":1,"x":0,"y":0}}`); reset(); settime(1) } } }, $leave(e) { // 玩家离开事件 let arr = j2(e); // 解析离开玩家的UUID ren = ren.filter(obj => obj.uuid !== arr); // 从玩家列表中移除该玩家 if (arr == player1.uuid) { send(`{"k":"msg","v":{"msg":"${player1.name}退出游戏结束"}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player1.uuid},"dir":1,"x":0,"y":0}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player2.uuid},"dir":1,"x":0,"y":0}}`); settime(1) reset() }else if(arr == player2.uuid){ send(`{"k":"msg","v":{"msg":"${player2.name}退出游戏结束"}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player1.uuid},"dir":1,"x":0,"y":0}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player2.uuid},"dir":1,"x":0,"y":0}}`); settime(1) reset() } }, $playerdata(e) { // 玩家数据更新事件 a(arr = j1(e)); // 更新玩家数据 }, $newplayer(e) { // 新玩家加入事件 const Data = JSON.parse(e); // 解析新玩家数据 const arr = [{ name: Data.v.name, uuid: Data.v.uuid, score: Data.v.score, x: Data.v.x, y: Data.v.y }]; ren = [...ren, ...arr]; // 将新玩家添加到玩家列表 }, mode(e) { // 模式切换事件 ren = []; // 清空玩家列表 }, msg(e) { let json = JSON.parse(e); if (json.v.msg == "/join" && of == "开") { if (player1.uuid == 0) { player1 = { uuid: json.v.uuid, name: json.v.name }; send(`{"k":"msg","v":{"msg":"${json.v.name}加入游戏"}}`); } else if (player2.uuid == 0 && player1.uuid !== json.v.uuid) { player2 = { uuid: json.v.uuid, name: json.v.name }; ren.forEach(player => { if(player.y < -300){ send(`{"k":"move","v":{"t":"throw","uuid":${player.uuid},"dir":1,"x":0,"y":0}}`); } }); send(`{"k":"msg","v":{"msg":"${json.v.name}和${player1.name}比赛开始计时两分钟"}}`); send(`{"k":"move","v":{"t":"throw","uuid":${json.v.uuid},"dir":1,"x":510,"y":-350}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player1.uuid},"dir":1,"x":950,"y":-350}}`); start = true settime(0) } else if (player1.uuid !== 0 && player2.uuid !== 0) { send(`{"k":"msg","v":{"msg":"${player1.name}和${player2.name}正在比赛"}}`); } } } }; // 定义全局变量存储定时器 ID let timerB, timerC; function settime(e) { // 定义定时器回调函数 function endGame() { if (score1 > score2) { send(`{"k":"msg","v":{"msg":"时间到,${player1.name}获胜"}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player1.uuid},"dir":1,"x":0,"y":0}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player2.uuid},"dir":1,"x":0,"y":0}}`); } else if (score2 > score1) { send(`{"k":"msg","v":{"msg":"时间到,${player2.name}获胜"}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player1.uuid},"dir":1,"x":0,"y":0}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player2.uuid},"dir":1,"x":0,"y":0}}`); } else { send(`{"k":"msg","v":{"msg":"${player1.name}和${player2.name}平局"}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player1.uuid},"dir":1,"x":0,"y":0}}`); send(`{"k":"move","v":{"t":"throw","uuid":${player2.uuid},"dir":1,"x":0,"y":0}}`); } reset(); // 确保 reset 函数已定义 } function halfTimeMessage() { send(`{"k":"msg","v":{"msg":"比赛过半,${player1.name}和${player2.name}请加油!"}}`); } if (e == 0) { // 启动计时器 timerB = setTimeout(endGame, 120000); // 120秒后执行 timerC = setTimeout(halfTimeMessage, 60000); // 60秒后执行 } else { // 清除计时器 if (timerB) clearTimeout(timerB); if (timerC) clearTimeout(timerC); console.log("定时器已清除"); } } function reset() { player1 = { name: "", uuid: 0 }; player2 = { name: "", uuid: 0 }; score1 = 0; score2 = 0; start = false; } let box = document.createElement('div'); box.id = "wtfhelp-container"; box.style.position = "absolute"; box.style.bottom = "10px"; box.style.right = "10px"; box.style.backgroundColor = "rgba(0, 0, 0, 0.7)"; box.style.padding = "10px"; box.style.borderRadius = "5px"; box.style.zIndex = "999999"; // 添加按钮 box.innerHTML = ` `; // 按钮点击事件处理 box.onclick = function(event) { if (event.target.id === "001") { if(of == "关"){ let r = qc.wtf.GameManager.instance.channel; if(r < 0){ send(`{"k":"msg","v":{"msg":"开启擂台"}}`); of = "开"; return; } else { alert("擂台仅可在py使用"); } } else if(of == "开"){ if (timerB) clearTimeout(timerB); if (timerC) clearTimeout(timerC); reset(); send(`{"k":"msg","v":{"msg":"关闭擂台"}}`); of = "关"; } } else if (event.target.id === "002" && of =="开") { if (timerB) clearTimeout(timerB); if (timerC) clearTimeout(timerC); reset(); send(`{"k":"msg","v":{"msg":"比赛强制结束,需重新加入"}}`); } else if (event.target.id === "003") { const roomNumber = prompt("输入房间号"); if (roomNumber !== null && roomNumber.trim() !== "") { send(`{"k":"msg","v":{"msg":"/room ${roomNumber.trim()}"}}`); } } }; document.body.appendChild(box); // 消息处理函数:根据消息类型调用对应的事件处理函数 function f(e) { for (const [event, handler] of Object.entries(eventHandlers)) { if (e.includes(event)) { // 如果消息中包含事件类型 handler(e); // 调用对应的事件处理函数 return; } } } // 更新玩家位置的函数 function a(arr) { if (arr[0].uuid !== me[0].uuid) { // 如果不是当前玩家 let ji = 0; for (let t = 0; t < ren.length; t++) { if (ren[t].uuid == arr[0].uuid) { // 如果玩家已存在 ren[t].x = arr[0].x; // 更新玩家的X坐标 ren[t].y = arr[0].y; // 更新玩家的Y坐标 } else { ji++; } } if (ji == ren.length) { // 如果玩家不存在 ren = [...ren, ...arr]; // 将新玩家添加到玩家列表 } } } // 解析单个玩家数据的函数 function j(jsonData) { const Data = JSON.parse(jsonData); // 解析JSON数据 const arr = [{ name: Data.v.name, uuid: Data.v.uuid, x: Data.v.x, y: Data.v.y }]; return arr; } // 解析多个玩家数据的函数 function j1(jsonData) { const Data = JSON.parse(jsonData); // 解析JSON数据 var arr = Data.v.map(item => { return { name: item.name, uuid: item.uuid, score: item.score, x: item.x, y: item.y }; }); return arr; } // 解析离开玩家的UUID function j2(jsonData) { const Data = JSON.parse(jsonData); // 解析JSON数据 const arr = Data.v.uuid; return arr; } // 处理发送数据的函数:更新当前玩家信息 function j3(datas) { if (datas.includes('move')) { // 如果是移动事件 me = j(datas); // 更新当前玩家信息 } else if (datas.includes('login')) { // 如果是登录事件 const Data = JSON.parse(datas); // 解析数据 me = [{ name: Data.v.name, uuid: 0, x: 0, y: 0 }]; } } // 加密函数:使用Base64加密 function jia(str) { return btoa(unescape(encodeURIComponent(str))); } // 解密函数 function jie(inputString) { try { // 尝试直接解码Base64字符串 let base64Decoded = atob(inputString); // 将解码后的二进制字符串转换为Uint8Array let bytes = new Uint8Array(base64Decoded.length); for (let i = 0; i < base64Decoded.length; i++) { bytes[i] = base64Decoded.charCodeAt(i); } // 使用TextDecoder将Uint8Array转换为UTF-8编码的字符串 let decoder = new TextDecoder('utf-8'); let decodedString = decoder.decode(bytes); return decodedString; // 直接返回解码后的字符串 } catch (e) { console.log('直接解码失败,尝试额外步骤:', e.message); try { // 分离Base64部分 let base64Part = inputString.split('==')[0] + '=='; // 确保字符串长度是4的倍数 while (base64Part.length % 4 !== 0) { base64Part = base64Part.replace('=', ''); } // 再次尝试解码Base64字符串 let base64Decoded = atob(base64Part); // 将解码后的二进制字符串转换为Uint8Array let bytes = new Uint8Array(base64Decoded.length); for (let i = 0; i < base64Decoded.length; i++) { bytes[i] = base64Decoded.charCodeAt(i); } // 使用TextDecoder将Uint8Array转换为UTF-8编码的字符串 let decoder = new TextDecoder('utf-8'); let decodedString = decoder.decode(bytes); // 提供的混合字符串 const mixedString = decodedString; // 初始化变量 let jsonPart = ''; let openBraces = 0; // 记录打开的花括号数量 // 遍历字符串的每个字符 for (let i = 0; i < mixedString.length; i++) { const char = mixedString[i]; jsonPart += char; // 添加当前字符到jsonPart if (char === '{') { openBraces++; // 遇到 '{',打开的花括号数量加1 } else if (char === '}') { openBraces--; // 遇到 '}',打开的花括号数量减1 } // 当打开的花括号数量为0时,说明已经找到一个完整的JSON对象 if (openBraces === 0) { break; } } return jsonPart; // 返回解码后的字符串 } catch (e) { return null; // 解码失败时返回null } } }