// ==UserScript==
// @name Florr.io Super Ping(开发版)
// @namespace http://tampermonkey.net/
// @version 2.1
// @license MIT
// @description Detects Super spawns in Florr.io, displays notifications, styled Super Ping messages, always visible, edge collision, language support, resizable UI, and hotkey recording. Includes a movable log window and UI toggles, with persistent UI positions.
// @author william
// @match https://florr.io/*
// @grant GM_addStyle
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @require https://code.jquery.com/jquery-3.6.0.min.js
// ==/UserScript==
(function() {
'use strict';
// 添加 CSS 样式
GM_addStyle(`
/* 设置按钮和语言按钮的共同容器 */
#button-container {
position: fixed;
bottom: 10px;
right: 10px;
display: flex; /* 使用 Flexbox 布局 */
align-items: center; /* 垂直居中 */
gap: 5px; /* 按钮之间的间距 */
z-index: 10001; /* 确保按钮在容器上方 */
}
#super-ping-container {
position: fixed;
top: 50%; /* 垂直居中 */
right: 10px; /* 靠右侧 */
transform: translateY(-50%); /* 垂直居中 */
background-color: rgba(0, 100, 0, 0.7); /* 深绿色背景 */
color: white;
padding: 15px; /* 增加内边距 */
border-radius: 5px;
z-index: 9999;
resize: both; /* 允许用户调整大小 */
overflow: auto; /* 确保内容不会溢出 */
font-family: sans-serif; /* 使用更清晰的字体 */
border: 2px solid #8FBC8F; /* 添加边框 */
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3); /* 添加阴影 */
font-size: 1.0em; /* 稍微增大字体大小 */
width: 300px; /* 设置初始宽度 */
height: 200px; /* 设置初始高度 */
}
#super-ping-container h3 {
margin-top: 0;
margin-bottom: 5px;
font-size: 1.4em; /* 稍微增大标题字体 */
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); /* 添加文字阴影 */
}
#super-ping-container p {
margin: 0;
font-size: 1.0em; /* 稍微增大字体大小 */
line-height: 1.4; /* 增加行高 */
}
#super-ping-history {
max-height: 200px; /* 增加历史记录高度 */
overflow-y: auto;
margin-top: 10px;
padding: 5px;
border: 1px solid #555;
border-radius: 3px;
background-color: rgba(0, 0, 0, 0.3); /* 历史记录背景 */
}
#super-ping-history p {
margin: 5px 0; /* 增加历史记录条目间距 */
font-size: 0.9em;
border-bottom: 1px solid #444; /* 添加分割线 */
padding-bottom: 5px; /* 增加底部内边距 */
}
#super-ping-history p:last-child {
border-bottom: none; /* 移除最后一个条目的分割线 */
}
#settings-container {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.8);
color: white;
padding: 20px;
border-radius: 10px;
z-index: 10000;
display: none; /* 初始状态隐藏 */
}
#settings-container label {
display: block;
margin-bottom: 5px;
}
#settings-container input,
#settings-container select {
margin-bottom: 10px;
padding: 5px;
border-radius: 3px;
border: none;
background-color: #333;
color: white;
}
#settings-container button {
background-color: #4CAF50;
color: white;
padding: 10px 15px;
border: none;
border-radius: 5px;
cursor: pointer;
}
#settings-container button:hover {
background-color: #3e8e41;
}
/* 调整大小手柄的样式 (可选) */
#super-ping-container::-webkit-resizer {
background: #444;
border: 1px solid #666;
}
/* Super Ping 消息样式 */
.super-text {
color: yellow; /* 修改为黄色 */
font-weight: bold; /* 加粗 */
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); /* 添加文字阴影 */
}
.entity-text {
color: lightblue; /* 修改为淡蓝色 */
}
/* 设置按钮样式 */
#settings-button {
background-color: rgba(0, 0, 0, 0.5);
color: white;
width: auto; /* 宽度自适应内容 */
height: auto; /* 高度自适应内容 */
min-width: 50px; /* 最小宽度 */
min-height: 50px; /* 最小高度 */
padding: 8px 12px; /* 内边距 */
border-radius: 0px; /* 设置为方形 */
cursor: pointer;
border: none; /* 移除边框 */
font-size: 16px; /* 调整字体大小 */
display: flex; /* 使用 Flexbox 布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
text-align: center; /* 确保文字居中 */
box-sizing: border-box; /* 确保内边距不影响总尺寸 */
}
#settings-button:hover {
background-color: rgba(0, 0, 0, 0.8);
}
/* 快捷语言切换按钮样式 */
#language-switch-button {
background-color: rgba(0, 0, 0, 0.5);
color: white;
width: auto; /* 宽度自适应内容 */
height: auto; /* 高度自适应内容 */
min-width: 50px; /* 最小宽度 */
min-height: 50px; /* 最小高度 */
padding: 8px 12px; /* 内边距 */
border-radius: 0px; /* 设置为方形 */
cursor: pointer;
border: none; /* 移除边框 */
font-size: 16px; /* 调整字体大小 */
display: flex; /* 使用 Flexbox 布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
text-align: center; /* 确保文字居中 */
box-sizing: border-box; /* 确保内边距不影响总尺寸 */
/* 限制语言切换按钮的最大宽度 */
max-width: 80px; /* 根据需要调整 */
overflow: hidden; /* 隐藏溢出的文本 */
white-space: nowrap; /* 防止文本换行 */
}
#language-switch-button:hover {
background-color: rgba(0, 0, 0, 0.8);
}
/* 快捷键录制样式 */
#hotkey-input {
cursor: pointer; /* 指示可点击 */
}
#hotkey-input.recording {
background-color: #ffc107; /* 醒目的颜色 */
color: black;
cursor: wait; /* 指示正在录制 */
}
/* 最后的 Super 样式 */
#last-super-info {
font-size: 1.2em; /* 增大字体 */
font-weight: bold; /* 加粗 */
margin-bottom: 5px; /* 增加间距 */
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); /* 添加文字阴影 */
}
/* Super 和 Server 标签样式 */
#super-type-label,
#super-server-label {
font-size: 0.9em; /* 减小字体 */
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); /* 添加文字阴影 */
}
/* Super 类型图标样式 */
#super-type {
display: inline-block; /* 确保 span 可以设置宽度和高度 */
width: 20px; /* 设置图标宽度 */
height: 20px; /* 设置图标高度 */
background-size: contain; /* 确保图标缩放到合适的大小 */
background-repeat: no-repeat; /* 防止图标重复 */
background-position: center; /* 居中显示图标 */
margin-right: 5px; /* 调整图标与文字的间距 */
}
/* Log Window Styles */
#log-container {
position: fixed;
top: 20px;
right: 20px;
background-color: rgba(0, 0, 0, 0.7); /* 半透明黑色背景 */
color: white;
padding: 10px;
border-radius: 5px;
z-index: 9998; /* 确保在 Super Ping 容器下方 */
resize: both;
overflow: auto;
font-family: monospace; /* 使用等宽字体 */
border: 1px solid #555;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
max-height: 400px; /* 设置最大高度 */
max-width: 500px; /* 设置最大宽度 */
font-size: 0.9em; /* 稍微增大字体大小 */
line-height: 1.4; /* 增加行高 */
min-width: 200px; /* 添加最小宽度 */
min-height: 100px; /* 添加最小高度 */
display: none; /* 初始状态隐藏 */
}
#log-container h3 {
margin-top: 0;
margin-bottom: 5px;
font-size: 1.1em;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
#log-output {
white-space: pre-wrap; /* 保留空格和换行 */
font-size: 0.8em;
line-height: 1.3;
word-break: break-word; /* 允许单词断行 */
}
/* Server Info Styles */
#server-info-container {
position: fixed;
bottom: 70px; /* 调整到 Settings 按钮上方 */
right: 10px; /* 与 Settings 按钮对齐 */
background-color: rgba(0, 0, 0, 0.5);
color: white;
padding: 8px;
border-radius: 3px;
font-size: 0.9em;
text-align: center;
z-index: 9997; /* 确保在 Super Ping 容器下方 */
display: none; /* 初始状态隐藏 */
}
/* Fullscreen Suggestion Styles */
#fullscreen-suggestion {
position: fixed;
top: 10px;
left: 50%;
transform: translateX(-50%);
background-color: rgba(255, 0, 0, 0.7); /* 设置背景颜色为红色,透明度为 0.7 */
color: yellow; /* 设置字体颜色为黄色 */
padding: 5px 10px; /* 稍微减小内边距 */
border-radius: 5px;
z-index: 10002; /* 确保在所有其他 UI 元素之上 */
font-size: 0.8em; /* 稍微减小字体大小 */
font-weight: bold;
text-align: center;
opacity: 0.9; /* 设置初始透明度 */
transition: opacity 1s ease-in-out; /* 添加过渡效果 */
display: flex; /* 使用 Flexbox 布局 */
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
}
#fullscreen-suggestion.fade-out {
opacity: 0; /* 设置透明度为 0 */
}
/* 警示图标样式 */
#fullscreen-suggestion::before {
content: "\\26A0"; /* Unicode 字符,表示警告符号 */
margin-right: 5px; /* 调整图标与文字的间距 */
font-size: 1em; /* 调整图标大小 */
}
/* FPS Counter Styles */
#fps-counter {
position: fixed;
bottom: 10px;
right: 150px; /* Adjust as needed to position next to other buttons */
background-color: rgba(0, 0, 0, 0.5);
color: white;
padding: 5px;
border-radius: 3px;
font-size: 0.9em;
z-index: 10001;
}
`);
// 全局变量
let lastSuperType = 'N/A';
let lastLocation = 'N/A';
let lastDirection = 'N/A';
let settingsVisible = false; // 添加一个变量来跟踪设置的可见性
// Super 类型图标映射
const superTypeIcons = {
'Super Queen Ant': 'https://i.imgur.com/your_queen_ant_icon.png',
'Super Beetle': 'https://i.imgur.com/your_beetle_icon.png',
'Super Spider': 'https://i.imgur.com/your_spider_icon.png'
};
// 服务器信息相关变量
let serverInfo = {
serverId: 'N/A'
};
// 函数:提取服务器 ID
function extractServerId(url) {
const match = url.match(/wss:\/\/([a-z0-9]*).s.m28n.net\//);
return match ? match[1] : null;
}
// 函数:获取服务器信息
function getServerInfo() {
const wsAddress = window.WebSocket.address; // 假设 WebSocket 地址存储在这个变量中
if (!wsAddress) return;
const serverId = extractServerId(wsAddress);
if (serverId) {
serverInfo.serverId = serverId;
updateServerInfoDisplay();
}
}
// 延迟执行,确保页面加载完成
setTimeout(() => {
// 创建 Super Ping 容器
let superPingContainer = document.createElement('div');
superPingContainer.id = 'super-ping-container';
superPingContainer.innerHTML = `
<h3 id="super-spawned-title">Super Ping</h3>
<div id="super-ping-history"></div>
`;
document.body.appendChild(superPingContainer);
// 创建设置容器
let settingsContainer = document.createElement('div');
settingsContainer.id = 'settings-container';
settingsContainer.style.display = 'none';
settingsContainer.innerHTML = `
<h2 id="settings-title">Settings</h2>
<label for="language" id="language-label">Language:</label>
<select id="language">
<option value="en">English</option>
<option value="zh">中文</option>
</select>
<label for="hotkey" id="hotkey-label">UI Hotkey (Show/Hide All):</label>
<input type="text" id="hotkey-input" value="Ctrl+Shift+S" readonly>
<label for="enable-log" id="enable-log-label">Enable Log UI:</label>
<input type="checkbox" id="enable-log">
<label for="enable-server-info" id="enable-server-info-label">Enable Server Info UI:</label>
<input type="checkbox" id="enable-server-info">
<button id="save-settings-button">Save Settings</button>
`;
document.body.appendChild(settingsContainer);
// 创建按钮容器
const buttonContainer = document.createElement('div');
buttonContainer.id = 'button-container';
document.body.appendChild(buttonContainer);
// 创建设置按钮
let settingsButton = document.createElement('button');
settingsButton.id = 'settings-button';
settingsButton.textContent = 'Settings';
buttonContainer.appendChild(settingsButton);
// 创建快捷语言切换按钮
let languageSwitchButton = document.createElement('button');
languageSwitchButton.id = 'language-switch-button';
buttonContainer.appendChild(languageSwitchButton);
console.log("Settings button:", settingsButton); // 调试:检查按钮元素是否被找到
// 创建日志容器
let logContainer = document.createElement('div');
logContainer.id = 'log-container';
logContainer.innerHTML = `
<h3>Log</h3>
<div id="log-output"></div>
`;
document.body.appendChild(logContainer);
// 创建服务器信息容器
let serverInfoContainer = document.createElement('div');
serverInfoContainer.id = 'server-info-container';
serverInfoContainer.innerHTML = `
Server ID: <span id="server-id">N/A</span>
<br>
Server: <span id="server-name">N/A</span>
`;
document.body.appendChild(serverInfoContainer);
// 获取服务器信息显示元素
const serverIdElement = document.getElementById('server-id');
const serverNameElement = document.getElementById('server-name');
// 函数:更新服务器信息显示
function updateServerInfoDisplay() {
serverIdElement.textContent = serverInfo.serverId;
serverNameElement.textContent = serverInfo.serverId; // 假设服务器名称与 ID 相同
}
// 获取设置元素
const languageSelect = document.getElementById('language');
let hotkeyInput = document.getElementById('hotkey-input'); // 获取快捷键输入框
const enableLogCheckbox = document.getElementById('enable-log');
const enableServerInfoCheckbox = document.getElementById('enable-server-info');
const saveSettingsButton = document.getElementById('save-settings-button');
// 加载设置
let language = GM_getValue('language', 'en');
// **自动检测浏览器语言**
const browserLanguage = navigator.language || navigator.userLanguage; // 获取浏览器语言
if (browserLanguage.startsWith('zh')) {
language = 'zh'; // 如果是中文,则设置为中文
} else {
language = 'en'; // 否则设置为英文
}
let hotkey = GM_getValue('hotkey', 'Ctrl+Shift+S');
let enableLog = GM_getValue('enableLog', false); // 默认隐藏 Log UI
let enableServerInfo = GM_getValue('enableServerInfo', true);
languageSelect.value = language;
hotkeyInput.value = hotkey;
enableLogCheckbox.checked = enableLog;
enableServerInfoCheckbox.checked = enableServerInfo;
// 初始化 UI 的显示状态
logContainer.style.display = enableLog ? 'block' : 'none';
serverInfoContainer.style.display = enableServerInfo ? 'block' : 'none';
// 保存设置
saveSettingsButton.addEventListener('click', () => {
language = languageSelect.value;
hotkey = hotkeyInput.value;
enableLog = enableLogCheckbox.checked;
enableServerInfo = enableServerInfoCheckbox.checked;
GM_setValue('language', language);
GM_setValue('hotkey', hotkey);
GM_setValue('enableLog', enableLog);
GM_setValue('enableServerInfo', enableServerInfo);
alert(getTranslation('settingsSaved'));
settingsContainer.style.display = 'none';
updateLanguage();
// 应用新的 UI 显示状态
logContainer.style.display = enableLog ? 'block' : 'none';
serverInfoContainer.style.display = enableServerInfo ? 'block' : 'none';
});
// 热键处理
document.addEventListener('keydown', (e) => {
const keys = [];
if (e.ctrlKey) keys.push('Ctrl');
if (e.shiftKey) keys.push('Shift');
if (e.altKey) keys.push('Alt');
keys.push(e.key.toUpperCase());
const pressedHotkey = keys.join('+');
// 全局 UI 快捷键
if (pressedHotkey === hotkey.toUpperCase()) {
settingsContainer.style.display = settingsContainer.style.display === 'none' ? 'block' : 'none';
superPingContainer.style.display = superPingContainer.style.display === 'none' ? 'block' : 'none';
logContainer.style.display = (enableLog && logContainer.style.display === 'none') ? 'block' : 'none';
serverInfoContainer.style.display = (enableServerInfo && serverInfoContainer.style.display === 'none') ? 'block' : 'none';
}
});
// 设置按钮点击事件
settingsButton.addEventListener('click', () => {
console.log("Settings button clicked"); // 调试:检查事件监听器是否被触发
console.log("settingsVisible before:", settingsVisible); // 调试:查看 settingsVisible 的值
settingsVisible = !settingsVisible; // 切换可见性
console.log("settingsVisible after:", settingsVisible); // 调试:查看 settingsVisible 的值
settingsContainer.style.display = settingsVisible ? 'block' : 'none'; // 根据可见性设置显示
console.log("settingsContainer.style.display:", settingsContainer.style.display); // 调试:查看 display 属性
});
// 快捷语言切换按钮点击事件
languageSwitchButton.addEventListener('click', () => {
language = (language === 'en') ? 'zh' : 'en';
GM_setValue('language', language);
updateLanguage();
});
// 获取 Super Server 和 Super Type 显示元素
const superPingHistoryElement = document.getElementById('super-ping-history');
// 获取需要翻译的元素
const superSpawnedTitle = document.getElementById('super-spawned-title');
const settingsTitle = document.getElementById('settings-title');
const languageLabel = document.getElementById('language-label');
const hotkeyLabel = document.getElementById('hotkey-label');
const enableLogLabel = document.getElementById('enable-log-label');
const enableServerInfoLabel = document.getElementById('enable-server-info-label');
const settingsButtonText = document.getElementById('settings-button');
// 翻译文本
const translations = {
en: {
superSpawned: 'Super Ping',
settings: 'Settings',
language: 'Language:',
hotkey: 'UI Hotkey (Show/Hide All):',
enableLog: 'Enable Log UI:',
enableServerInfo: 'Enable Server Info UI:',
saveSettings: 'Save Settings',
settingsSaved: 'Settings saved!',
spawnedOn: 'spawned on',
superSpawnedSomewhere: 'A Super has spawned somewhere!',
serverId: 'Server ID:',
server: 'Server:',
chinese: '中文',
fullscreenSuggestion: '⚠️ For the best experience, it is recommended to play in fullscreen.'
},
zh: {
superSpawned: 'Super Ping',
settings: '设置',
language: '语言:',
hotkey: 'UI 快捷键 (显示/隐藏全部):',
enableLog: '启用日志 UI:',
enableServerInfo: '启用服务器信息 UI:',
saveSettings: '保存设置',
settingsSaved: '设置已保存!',
spawnedOn: '生成于',
superSpawnedSomewhere: '某个地方生成了一个 Super!',
serverId: '服务器 ID:',
server: '服务器:',
chinese: 'English',
fullscreenSuggestion: '⚠️ 为了获得最佳体验,建议全屏游玩。'
}
};
// 函数:获取翻译文本
function getTranslation(key) {
return translations[language][key] || translations['en'][key] || key;
}
// 函数:更新语言
function updateLanguage() {
language = GM_getValue('language', 'en');
superSpawnedTitle.textContent = getTranslation('superSpawned');
settingsTitle.textContent = getTranslation('settings');
languageLabel.textContent = getTranslation('language');
hotkeyLabel.textContent = getTranslation('hotkey');
enableLogLabel.textContent = getTranslation('enableLog');
enableServerInfoLabel.textContent = getTranslation('enableServerInfo');
saveSettingsButton.textContent = getTranslation('saveSettings');
settingsButtonText.textContent = getTranslation('settings');
languageSwitchButton.textContent = getTranslation('chinese');
// 翻译 Super Ping 历史记录
const historyEntries = document.querySelectorAll('#super-ping-history p');
historyEntries.forEach(entry => {
// 获取原始消息中的位置和时间信息
const parts = entry.textContent.split(' - ');
const locationAndTime = parts.slice(0, 2).join(' - '); // 位置和时间
const translatedMessage = getTranslation('superSpawnedSomewhere'); // 翻译后的消息
// 组合位置、时间和翻译后的消息
entry.textContent = `${locationAndTime} - ${translatedMessage}`;
});
// 翻译服务器信息
document.querySelector('#server-info-container').innerHTML = `${getTranslation('serverId')} <span id="server-id">${serverInfo.serverId}</span><br>${getTranslation('server')} <span id="server-name">${serverInfo.serverId}</span>`;
// 翻译全屏提示
if (fullscreenSuggestion) { // 检查 fullscreenSuggestion 是否存在
fullscreenSuggestion.textContent = getTranslation('fullscreenSuggestion');
}
// Update FPS counter position after language change
updateFPSCounterPosition();
}
// 函数:显示 Super Ping
function showSuperPing(superType, location, direction) {
console.log('showSuperPing called', superType, location, direction);
try {
const historyEntry = document.createElement('p');
const translatedMessage = getTranslation('superSpawnedSomewhere');
historyEntry.textContent = `${location} - ${new Date().toLocaleTimeString()} - ${translatedMessage}`;
superPingHistoryElement.insertBefore(historyEntry, superPingHistoryElement.firstChild);
while (superPingHistoryElement.children.length > 10) {
superPingHistoryElement.removeChild(superPingHistoryElement.lastChild);
}
logMessage(`Super spawned: ${superType} at ${location}`);
} catch (error) {
console.error('Error in showSuperPing:', error);
logMessage(`Error showing Super Ping: ${error.message}`);
}
}
// 模拟 Super 生成
setInterval(() => {
const superTypes = ['Super Queen Ant', 'Super Beetle', 'Super Spider'];
const randomSuperType = superTypes[Math.floor(Math.random() * superTypes.length)];
const randomLocation = ['US-Desert-1k73-2025/2/19', 'EU-Forest-2j84-2025/2/19', 'AS-Mountain-3l95-2025/2/19'][Math.floor(Math.random() * 3)];
const randomDirection = ['North', 'South', 'East', 'West'][Math.floor(Math.random() * 4)];
showSuperPing(randomSuperType, randomLocation, randomDirection);
}, 15000);
// 快捷键录制
let isRecording = false;
//const hotkeyInput = document.getElementById('hotkey-input'); // 获取快捷键输入框
hotkeyInput.addEventListener('click', () => {
startRecordingHotkey(hotkeyInput);
});
function startRecordingHotkey(inputElement) {
isRecording = true;
inputElement.value = 'Recording...';
inputElement.classList.add('recording');
}
document.addEventListener('keydown', (e) => {
if (isRecording) {
e.preventDefault();
const keys = [];
if (e.ctrlKey) keys.push('Ctrl');
if (e.shiftKey) keys.push('Shift');
if (e.altKey) keys.push('Alt');
keys.push(e.key.toUpperCase());
const recordedHotkey = keys.join('+');
if (hotkeyInput.classList.contains('recording')) {
hotkeyInput.value = recordedHotkey;
GM_setValue('hotkey', recordedHotkey);
}
isRecording = false;
hotkeyInput.classList.remove('recording');
} else {
// 如果不是在录制快捷键,则检查是否按下了隐藏/显示 UI 的快捷键
const keys = [];
if (e.ctrlKey) keys.push('Ctrl');
if (e.shiftKey) keys.push('Shift');
if (e.altKey) keys.push('Alt');
keys.push(e.key.toUpperCase());
const pressedHotkey = keys.join('+');
// 全局 UI 快捷键
if (pressedHotkey === hotkey.toUpperCase()) {
settingsContainer.style.display = settingsContainer.style.display === 'none' ? 'block' : 'none';
superPingContainer.style.display = superPingContainer.style.display === 'none' ? 'block' : 'none';
logContainer.style.display = (enableLog && logContainer.style.display === 'none') ? 'block' : 'none';
serverInfoContainer.style.display = (enableServerInfo && serverInfoContainer.style.display === 'none') ? 'block' : 'none';
}
}
});
// 日志功能
const logOutput = document.getElementById('log-output');
function logMessage(message) {
const timestamp = new Date().toLocaleTimeString();
logOutput.textContent += `[${timestamp}] ${message}\n`;
logOutput.scrollTop = logOutput.scrollHeight;
}
// 初始日志消息
logMessage('Script started.');
// --- 服务器信息相关 ---
// Hook WebSocket
const originalWebSocket = window.WebSocket;
window.WebSocket = function(url, protocols) {
window.WebSocket.address = url; // 存储 WebSocket 地址
getServerInfo(); // 获取服务器信息
if (protocols) {
return new originalWebSocket(url, protocols);
} else {
return new originalWebSocket(url);
}
};
window.WebSocket.prototype = originalWebSocket.prototype;
// 初始化服务器信息
getServerInfo();
// 使用 MutationObserver 监听 Super Ping 历史记录的变化
const observer = new MutationObserver((mutationsList, observer) => {
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {
// 当有节点被添加或删除时,更新语言
updateLanguage();
}
}
});
// 开始监听 Super Ping 历史记录容器
const superPingHistoryElementForObserver = document.getElementById('super-ping-history');
observer.observe(superPingHistoryElementForObserver, { childList: true });
// 创建全屏提示 UI
const fullscreenSuggestion = document.createElement('div');
console.log("Fullscreen suggestion element created:", fullscreenSuggestion); // Debugging
fullscreenSuggestion.id = 'fullscreen-suggestion';
document.body.appendChild(fullscreenSuggestion);
console.log("Fullscreen suggestion element appended:", fullscreenSuggestion); // Debugging
// 20 秒后移除全屏提示
setTimeout(() => {
fullscreenSuggestion.classList.add('fade-out');
setTimeout(() => {
fullscreenSuggestion.remove();
}, 1000); // 1 秒后移除元素,与 CSS 过渡时间一致
}, 20000);
// --- FPS Counter ---
let fpsCounter = document.createElement('div');
fpsCounter.id = 'fps-counter';
document.body.appendChild(fpsCounter);
let lastFrameTime = performance.now();
let frameCount = 0;
let fps = 0;
function updateFPS() {
const now = performance.now();
const delta = now - lastFrameTime;
lastFrameTime = now;
fps = Math.round(1000 / delta);
fpsCounter.textContent = `FPS: ${fps}`;
frameCount++;
requestAnimationFrame(
() => updateFPS());
}
// Function to update FPS counter position
function updateFPSCounterPosition() {
const settingsButton = document.getElementById('settings-button');
const fpsCounter = document.getElementById('fps-counter');
if (settingsButton && fpsCounter) {
// Calculate the left position based on the settings button's position
const settingsButtonRect = settingsButton.getBoundingClientRect();
const fpsCounterWidth = fpsCounter.offsetWidth;
const newLeft = settingsButtonRect.left - fpsCounterWidth - 5; // 5px gap
// Set the new left position
fpsCounter.style.left = `${newLeft}px`;
fpsCounter.style.right = 'auto'; // Important: Reset right style
}
}
updateFPS(); // Start the FPS counter
// --- Initial Language Update ---
updateLanguage();
}, 1000);
})();