您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Server switcher for powerline
当前为
- // ==UserScript==
- // @name Powerline Server Switcher
- // @author Rumini - Discord: rumini & zaynbieber
- // @description Server switcher for powerline
- // @version 1.0
- // @match *://powerline.io/*
- // @icon https://i.imgur.com/9k4SFr0.png
- // @license MIT
- // @grant none
- // @run-at document-start
- // @namespace https://greasyfork.org/users/1356205
- // ==/UserScript==
- if (window.location.href === 'https://powerline.io/') {
- window.location.href = 'https://powerline.io/maindev.html';
- }
- (function () {
- 'use strict';
- // Configuration
- const CONFIG = {
- regions: ['Europe', 'Asia', 'America'],
- countryCodes: { Europe: 'DE', Asia: 'JP', America: 'US' },
- euCountries: new Set(['AL', 'AD', 'AT', 'BY', 'BE', 'BA', 'BG', 'HR', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HU', 'IS', 'IE', 'IT', 'LV', 'LI', 'LT', 'LU', 'MT', 'MC', 'NL', 'NO', 'PL', 'PT', 'RO', 'RU', 'SM', 'RS', 'SK', 'SI', 'ES', 'SE', 'CH', 'UA', 'GB', 'VA']),
- asiaCountries: new Set(['AF', 'AM', 'AZ', 'BH', 'BD', 'BT', 'BN', 'KH', 'CN', 'CY', 'GE', 'IN', 'ID', 'IR', 'IQ', 'IL', 'JP', 'JO', 'KZ', 'KW', 'KG', 'LA', 'LB', 'MY', 'MV', 'MN', 'MM', 'NP', 'KP', 'OM', 'PK', 'PS', 'PH', 'QA', 'SA', 'SG', 'KR', 'LK', 'SY', 'TW', 'TJ', 'TH', 'TR', 'TM', 'AE', 'UZ', 'VN', 'YE']),
- updateInterval: 1000,
- hideDelay: 1000,
- switchDelay: 1000,
- tipDuration: 2000,
- };
- // Utility functions
- const util = {
- waitForGame: (callback) => {
- if (typeof network !== 'undefined' && typeof countryCode !== 'undefined') {
- callback();
- } else {
- setTimeout(() => util.waitForGame(callback), 100);
- }
- },
- getRegion: () => {
- if (CONFIG.euCountries.has(countryCode)) return 'Europe';
- if (CONFIG.asiaCountries.has(countryCode)) return 'Asia';
- return 'America';
- },
- createElement: (tag, options = {}) => {
- const element = document.createElement(tag);
- Object.assign(element, options);
- if (options.style) element.style.cssText = options.style;
- return element;
- },
- };
- // Main class
- class ServerSwitcher {
- constructor() {
- this.elements = {};
- this.state = {
- isRegionSelectorOpen: false,
- isRoomCodeInputActive: false,
- };
- this.hideTimeout = null;
- }
- init() {
- this.createUI();
- this.attachEventListeners();
- this.updateServerInfo();
- setInterval(() => this.updateServerInfo(), CONFIG.updateInterval);
- }
- createUI() {
- this.elements = {
- container: util.createElement('div', {
- id: 'server-info-container',
- style: `
- position: absolute;
- top: 0px;
- right: 0px;
- display: flex;
- align-items: center;
- z-index: 1000;
- opacity: 0;
- `
- }),
- switcherContainer: util.createElement('div', {
- id: 'region-switcher-container',
- style: `
- position: relative;
- display: flex;
- align-items: center;
- margin-right: 10px;
- `
- }),
- switcherButton: util.createElement('button', {
- id: 'region-switcher',
- innerHTML: `
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" width="30" height="30">
- <path fill="#00ffff" d="M0 96C0 43 43 0 96 0L384 0l32 0c17.7 0 32 14.3 32 32l0 320c0 17.7-14.3 32-32 32l0 64c17.7 0 32 14.3 32 32s-14.3 32-32 32l-32 0L96 512c-53 0-96-43-96-96L0 96zM64 416c0 17.7 14.3 32 32 32l256 0 0-64L96 384c-17.7 0-32 14.3-32 32zM247.4 283.8c-3.7 3.7-6.2 4.2-7.4 4.2s-3.7-.5-7.4-4.2c-3.8-3.7-8-10-11.8-18.9c-6.2-14.5-10.8-34.3-12.2-56.9l63 0c-1.5 22.6-6 42.4-12.2 56.9c-3.8 8.9-8 15.2-11.8 18.9zm42.7-9.9c7.3-18.3 12-41.1 13.4-65.9l31.1 0c-4.7 27.9-21.4 51.7-44.5 65.9zm0-163.8c23.2 14.2 39.9 38 44.5 65.9l-31.1 0c-1.4-24.7-6.1-47.5-13.4-65.9zM368 192a128 128 0 1 0 -256 0 128 128 0 1 0 256 0zM145.3 208l31.1 0c1.4 24.7 6.1 47.5 13.4 65.9c-23.2-14.2-39.9-38-44.5-65.9zm31.1-32l-31.1 0c4.7-27.9 21.4 51.7 44.5 65.9c-7.3 18.3-12 41.1-13.4 65.9zm56.1-75.8c3.7-3.7 6.2-4.2 7.4-4.2s3.7 .5 7.4 4.2c3.8 3.7 8 10 11.8 18.9c6.2 14.5 10.8 34.3 12.2 56.9l-63 0c1.5-22.6 6-42.4 12.2-56.9c3.8-8.9 8-15.2 11.8-18.9z"/>
- </svg>
- `,
- style: `
- background: none;
- border: none;
- cursor: pointer;
- padding: 5px;
- display: flex;
- align-items: center;
- `
- }),
- roomCodeInput: util.createElement('input', {
- type: 'text',
- placeholder: 'Enter room code',
- style: `
- position: absolute;
- top: 50%;
- right: 0;
- transform: translateY(-50%);
- width: 0;
- padding: 5px;
- border: #05ffff solid;
- border-width: 2px;
- border-radius: 5px;
- background-color: #003a3a;
- color: #05ffff;
- font-family: 'Arial', sans-serif;
- font-size: 14px;
- transition: width 0.3s ease-out, opacity 0.3s ease-out;
- opacity: 0;
- outline: none;
- `
- }),
- infoDiv: util.createElement('div', {
- id: 'server-info',
- style: `
- background-color: #003a3a;
- border-radius: 5px;
- padding: 3px 6px;
- border: #05ffff solid;
- border-width: 2px;
- border-radius: 0 0 0 5px;
- color: #05ffff;
- font-family: 'Arial Black', sans-serif;
- font-size: 14px;
- user-select: none;
- cursor: pointer;
- `
- }),
- regionOptions: []
- };
- this.createRegionOptions();
- this.elements.switcherContainer.append(this.elements.switcherButton, this.elements.roomCodeInput);
- this.elements.container.append(this.elements.switcherContainer, this.elements.infoDiv);
- document.body.appendChild(this.elements.container);
- }
- createRegionOptions() {
- CONFIG.regions.forEach((region, index) => {
- const option = util.createElement('div', {
- textContent: region,
- style: `
- position: absolute;
- right: -70px;
- top: 50%;
- transform: translateY(-50%) translateX(0);
- padding: 5px;
- cursor: pointer;
- color: #05ffff;
- background: rgba(0, 58, 58, 0.7);
- backdrop-filter: blur(5px);
- border: 1px solid rgba(5, 255, 255, 0.3);
- border-radius: 5px;
- opacity: 0;
- transition: opacity 0.3s ease-out, transform 0.3s ease-out;
- z-index: ${1000 - index};
- width: 70px;
- text-align: center;
- `
- });
- option.addEventListener('click', (e) => {
- e.stopPropagation();
- this.switchRegion(index);
- });
- this.elements.switcherContainer.appendChild(option);
- this.elements.regionOptions.push(option);
- });
- }
- attachEventListeners() {
- this.elements.infoDiv.addEventListener('click', () => this.copyRoomLink());
- this.elements.switcherContainer.addEventListener('mouseenter', () => this.handleContainerMouseEnter());
- this.elements.switcherContainer.addEventListener('mouseleave', () => this.handleContainerMouseLeave());
- this.elements.switcherButton.addEventListener('click', (e) => this.handleSwitcherButtonClick(e));
- this.elements.roomCodeInput.addEventListener('keydown', (e) => this.handleRoomCodeInputKeydown(e));
- document.addEventListener('click', (e) => this.handleDocumentClick(e));
- }
- updateServerInfo() {
- const roomCode = network.roomID ? `#${network.roomID}` : 'Not in a room';
- const region = util.getRegion();
- if (typeof localPlayer === 'undefined' || localPlayerID === 0) {
- this.elements.infoDiv.innerHTML = `Room: ${roomCode}<br>Region: ${region}`;
- this.elements.container.style.cssText += `
- transition: opacity ease-in 0.25s;
- transition-delay: 0.3s;
- opacity: 1;
- `;
- } else {
- this.elements.container.style.cssText += `
- transition: none;
- opacity: 0;
- `;
- }
- }
- switchRegion(index) {
- const newRegion = CONFIG.regions[index];
- const newCC = CONFIG.countryCodes[newRegion];
- countryCode = newCC;
- window.localStorage.wingsCC = newCC;
- window.localStorage.wingsCCTime = Date.now();
- network.disconnect();
- setTimeout(() => network.getServerAndConnect(), CONFIG.switchDelay);
- hud.showTip(`Switched to region: ${newRegion}`, CONFIG.tipDuration);
- }
- toggleRegions() {
- this.state.isRegionSelectorOpen = !this.state.isRegionSelectorOpen;
- this.state.isRegionSelectorOpen ? this.showRegions() : this.hideRegions();
- }
- showRegions() {
- clearTimeout(this.hideTimeout);
- this.elements.regionOptions.forEach((option, index) => {
- option.style.cssText += `
- opacity: 1;
- transform: translateY(-50%) translateX(${-120 - index * 90}px);
- `;
- });
- }
- hideRegions() {
- this.elements.regionOptions.forEach((option) => {
- option.style.cssText += `
- opacity: 0;
- transform: translateY(-50%) translateX(-80%);
- `;
- });
- }
- showRoomCodeInput() {
- this.state.isRoomCodeInputActive = true;
- this.elements.roomCodeInput.style.cssText += `
- width: 120px;
- opacity: 1;
- pointer-events: auto;
- `;
- this.elements.switcherButton.style.cssText += `
- opacity: 0;
- pointer-events: none;
- `;
- this.elements.roomCodeInput.focus();
- this.hideRegions();
- }
- hideRoomCodeInput() {
- this.state.isRoomCodeInputActive = false;
- this.elements.roomCodeInput.style.cssText += `
- width: 0;
- opacity: 0;
- pointer-events: none;
- `;
- this.elements.switcherButton.style.cssText += `
- opacity: 1;
- pointer-events: auto;
- `;
- this.showRegions();
- }
- connectToRoom(roomCode) {
- if (roomCode) {
- network.disconnect();
- setTimeout(() => {
- window.location.hash = roomCode;
- network.getServerAndConnect();
- }, CONFIG.switchDelay);
- hud.showTip(`Connecting to room: ${roomCode}`, CONFIG.tipDuration);
- this.updateServerInfo();
- }
- }
- copyRoomLink() {
- const roomCode = network.roomID ? `#${network.roomID}` : '';
- const url = `http://powerline.io/${roomCode}`;
- navigator.clipboard.writeText(url)
- .then(() => console.log('Copied to clipboard:', url))
- .catch(err => console.error('Failed to copy to clipboard:', err));
- }
- handleContainerMouseEnter() {
- clearTimeout(this.hideTimeout);
- if (!this.state.isRegionSelectorOpen && !this.state.isRoomCodeInputActive) {
- this.showRegions();
- }
- }
- handleContainerMouseLeave() {
- if (!this.state.isRegionSelectorOpen && !this.state.isRoomCodeInputActive) {
- this.hideTimeout = setTimeout(() => this.hideRegions(), CONFIG.hideDelay);
- }
- }
- handleSwitcherButtonClick(e) {
- e.stopPropagation();
- this.state.isRoomCodeInputActive ? this.hideRoomCodeInput() : this.showRoomCodeInput();
- }
- handleRoomCodeInputKeydown(e) {
- if (e.key === 'Enter') {
- this.connectToRoom(this.elements.roomCodeInput.value);
- this.hideRoomCodeInput();
- } else if (e.key === 'Escape') {
- this.hideRoomCodeInput();
- }
- }
- handleDocumentClick(e) {
- if (!this.elements.switcherContainer.contains(e.target)) {
- if (this.state.isRegionSelectorOpen) {
- this.toggleRegions();
- }
- if (this.state.isRoomCodeInputActive) {
- this.hideRoomCodeInput();
- }
- }
- }
- }
- // Initialize the ServerSwitcher when the game is ready
- util.waitForGame(() => new ServerSwitcher().init());
- })();