// ==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
}
}
}