Last active
February 27, 2025 13:01
-
-
Save maanimis/42dd254450a10f8f087ae8447d8c91ee to your computer and use it in GitHub Desktop.
Reconnecting WebSocket for territorial.io-Violentmonkey Scripts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Reconnecting WebSocket-territorial.io | |
| // @namespace Violentmonkey Scripts | |
| // @match https://territorial.io/* | |
| // @grant none | |
| // @version 3.2 | |
| // @description Reconnecting WebSocket for territorial.io with improved stability. | |
| // @run-at document-start | |
| // ==/UserScript== | |
| console.log("Running WebSocket injector..."); | |
| const OriginalWebSocket = WebSocket; | |
| let shouldReconnect = true; // Track whether we should attempt to reconnect | |
| let reconnectAttempts = 0; | |
| const maxReconnectAttempts = 30; | |
| const baseReconnectDelay = 1000; // Initial delay (1s) | |
| let wsInstance = null; | |
| window.WebSocket = function (url, protocols) { | |
| const ws = new OriginalWebSocket(url, protocols); | |
| wsInstance = ws; | |
| const eventListeners = { | |
| open: [], | |
| message: [], | |
| close: [], | |
| error: [], | |
| }; | |
| const reconnect = () => { | |
| if (!shouldReconnect || reconnectAttempts >= maxReconnectAttempts) { | |
| console.warn("Max reconnection attempts reached or manual close detected."); | |
| return; | |
| } | |
| const reconnectDelay = baseReconnectDelay * Math.pow(2, reconnectAttempts); | |
| console.info(`Reconnecting in ${reconnectDelay / 1000} seconds... (Attempt ${reconnectAttempts + 1})`); | |
| setTimeout(() => { | |
| reconnectAttempts++; | |
| const newSocket = new OriginalWebSocket(url, protocols); | |
| wsInstance = newSocket; | |
| // Restore event listeners | |
| for (const eventType in eventListeners) { | |
| eventListeners[eventType].forEach(listener => newSocket.addEventListener(eventType, listener)); | |
| } | |
| newSocket.addEventListener("close", (event) => { | |
| console.warn(`WebSocket closed: Code ${event.code}, Reason: ${event.reason || "No reason provided."}`); | |
| if (shouldReconnect) reconnect(); | |
| }); | |
| newSocket.addEventListener("error", () => { | |
| console.error("WebSocket encountered an error. Attempting to reconnect..."); | |
| reconnect(); | |
| }); | |
| reconnectAttempts = 0; // Reset attempts on successful reconnection | |
| console.info("Reconnected successfully."); | |
| }, reconnectDelay); | |
| }; | |
| ws.addEventListener("error", () => { | |
| console.error("WebSocket error occurred. Reconnecting..."); | |
| reconnect(); | |
| }); | |
| ws.addEventListener("close", (event) => { | |
| console.warn(`WebSocket closed: Code ${event.code}, Reason: ${event.reason || "No reason provided."}`); | |
| if (shouldReconnect) reconnect(); | |
| }); | |
| // Intercept addEventListener to store custom listeners | |
| const originalAddEventListener = ws.addEventListener.bind(ws); | |
| ws.addEventListener = (type, listener, options) => { | |
| if (eventListeners[type]) { | |
| eventListeners[type].push(listener); | |
| } | |
| originalAddEventListener(type, listener, options); | |
| }; | |
| // Intercept removeEventListener to properly clean up | |
| const originalRemoveEventListener = ws.removeEventListener.bind(ws); | |
| ws.removeEventListener = (type, listener, options) => { | |
| if (eventListeners[type]) { | |
| eventListeners[type] = eventListeners[type].filter(l => l !== listener); | |
| } | |
| originalRemoveEventListener(type, listener, options); | |
| }; | |
| // Override close method to track manual closures | |
| const originalClose = ws.close.bind(ws); | |
| ws.close = (code, reason) => { | |
| shouldReconnect = false; // Stop reconnecting if manually closed | |
| console.info(`WebSocket manually closed: Code ${code}, Reason: ${reason || "No reason provided."}`); | |
| originalClose(code, reason); | |
| }; | |
| console.log("New WebSocket connection established!"); | |
| return ws; | |
| }; | |
| /* | |
| // ==UserScript== | |
| // @name Reconnecting WebSocket-territorial.io | |
| // @namespace Violentmonkey Scripts | |
| // @match https://territorial.io/* | |
| // @grant none | |
| // @version 3.2 | |
| // @description Reconnecting WebSocket for territorial.io with backoff and cleanup. | |
| // @run-at document-start | |
| // ==/UserScript== | |
| console.log("Running WebSocket injector..."); | |
| const OriginalWebSocket = WebSocket; | |
| window.WebSocket = function (url, protocols) { | |
| let ws = new OriginalWebSocket(url, protocols); | |
| let reconnectAttempts = 0; | |
| const maxReconnectAttempts = 30; | |
| const baseReconnectDelay = 1000; // Starting delay in ms | |
| const maxReconnectDelay = 30000; // Cap delay at 30 seconds | |
| let isReconnecting = false; | |
| let reconnectTimeout = null; | |
| const customListeners = { | |
| open: [], | |
| message: [], | |
| close: [], | |
| error: [], | |
| }; | |
| const calculateDelay = () => { | |
| // Exponential backoff: 1s, 2s, 4s, 8s, ..., capped at maxReconnectDelay | |
| // const delay = Math.min(baseReconnectDelay * Math.pow(2, reconnectAttempts), maxReconnectDelay); | |
| // return delay + Math.random() * 1000; // Add jitter to avoid synchronized retries | |
| return this.baseReconnectDelay | |
| }; | |
| const reconnect = () => { | |
| if (isReconnecting || reconnectAttempts >= maxReconnectAttempts || ws.readyState === WebSocket.OPEN) { | |
| if (reconnectAttempts >= maxReconnectAttempts) { | |
| console.warn("Max reconnection attempts reached."); | |
| } | |
| return; | |
| } | |
| isReconnecting = true; | |
| reconnectAttempts++; | |
| const delay = calculateDelay(); | |
| console.info(`Reconnecting... Attempt ${reconnectAttempts} after ${Math.round(delay)}ms`); | |
| reconnectTimeout = setTimeout(() => { | |
| // Clean up the old WebSocket | |
| if (ws && ws.readyState !== WebSocket.CLOSED) { | |
| ws.close(); | |
| } | |
| // Create new WebSocket | |
| const newSocket = new OriginalWebSocket(url, protocols); | |
| newSocket.onopen = ws.onopen; | |
| newSocket.onmessage = ws.onmessage; | |
| newSocket.onclose = ws.onclose; | |
| newSocket.onerror = ws.onerror; | |
| // Reattach custom listeners | |
| for (const eventType in customListeners) { | |
| customListeners[eventType].forEach((listener) => { | |
| newSocket.addEventListener(eventType, listener); | |
| }); | |
| } | |
| // Replace the old WebSocket reference | |
| ws = newSocket; | |
| // Reset state on successful reconnection | |
| newSocket.addEventListener("open", () => { | |
| reconnectAttempts = 0; | |
| isReconnecting = false; | |
| console.info("Reconnected successfully."); | |
| }); | |
| // Handle errors on the new socket | |
| newSocket.addEventListener("error", handleError); | |
| reconnectTimeout = null; | |
| }, delay); | |
| }; | |
| const handleError = () => { | |
| console.error("WebSocket encountered an error. Attempting to reconnect..."); | |
| reconnect(); | |
| }; | |
| ws.addEventListener("error", handleError); | |
| const originalAddEventListener = ws.addEventListener.bind(ws); | |
| ws.addEventListener = (type, listener, options) => { | |
| if (customListeners[type]) { | |
| customListeners[type].push(listener); | |
| } | |
| originalAddEventListener(type, listener, options); | |
| }; | |
| const originalRemoveEventListener = ws.removeEventListener.bind(ws); | |
| ws.removeEventListener = (type, listener, options) => { | |
| if (customListeners[type]) { | |
| customListeners[type] = customListeners[type].filter((l) => l !== listener); | |
| } | |
| originalRemoveEventListener(type, listener, options); | |
| }; | |
| const originalClose = ws.close.bind(ws); | |
| ws.close = (code, reason) => { | |
| console.warn(`WebSocket closed: Code ${code}, Reason: ${reason || "No reason provided."}`); | |
| if (reconnectTimeout) { | |
| clearTimeout(reconnectTimeout); | |
| reconnectTimeout = null; | |
| } | |
| originalClose(code, reason); | |
| if (!isReconnecting) { | |
| console.info("WebSocket closed manually."); | |
| reconnect(); | |
| } | |
| }; | |
| console.log("New WebSocket connection opened!"); | |
| // Add a method to disable reconnection | |
| ws.disableReconnect = () => { | |
| if (reconnectTimeout) { | |
| clearTimeout(reconnectTimeout); | |
| reconnectTimeout = null; | |
| } | |
| reconnectAttempts = maxReconnectAttempts; // Prevent further attempts | |
| console.info("Reconnection disabled."); | |
| }; | |
| return ws; | |
| }; | |
| */ | |
Author
How should I use this code? I tried running the code in the console while the game was loading, but it didn't work. After 4 and a half minutes, the game still closes the WS connection.
Yes, unfortunately, the code has a bug.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How should I use this code? I tried running the code in the console while the game was loading, but it didn't work. After 4 and a half minutes, the game still closes the WS connection.