您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Replaces default city/country names and flags with Lithuanian city and district names and coats of arms on richup.io game pages.
当前为
// ==UserScript== // @name Richup.io Name & Flag Replacer (Lithuanian Cities) // @namespace http://tampermonkey.net/ // @version 1.0 // @description Replaces default city/country names and flags with Lithuanian city and district names and coats of arms on richup.io game pages. // @author Giedrius Rackevicius // @match https://richup.io/room/* // @grant none // @run-at document-idle // ==/UserScript== (function () { "use strict"; // --- Configuration: Text Replacements (Old Name -> New Name) --- const textReplacements = { // Marijampolė Brazil: "Marijampolė", Salvador: "Degučiai", Rio: "Mokolai", // Utena Israel: "Utena", "Tel Aviv": "Vyturiai", Haifa: "Dauniškis", Jerusalem: "Aukštakalnis", // Alytus Italy: "Alytus", Venice: "Vidzgiris", Milan: "Putinai", Rome: "Dainava", // Panevėžys Germany: "Panevėžys", Frankfurt: "Tulpės", Munich: "Pilėnai", Berlin: "Senvagė", // Note: Berlin mapped to Senvagė like Frankfurt // Šiauliai China: "Šiauliai", Shenzhen: "Dainai", Beijing: "Zokniai", Shanghai: "Didždvaris", // Klaipėda France: "Klaipėda", Lyon: "Baltija", Toulouse: "Rumpiškė", Paris: "Vėtrungė", // Kaunas "United Kingdom": "Kaunas", Liverpool: "Žaliakalnis", Manchester: "Šilainiai", London: "Centras", // Vilnius USA: "Vilnius", "San Francisco": "Naujamiestis", "New York": "Senamiestis", // Airports "TLV Airport": "SQQ Airport", "MUC Airport": "PLQ Airport", "CDG Airport": "KUN Airport", "JFK Airport": "VNO Airport", // Companies "Electric Company": "Ignitis", "Water Company": "Utenos Vandenys", }; // Helper to normalize SVG strings for consistent matching const normalizeSvgString = (svgString) => { if (!svgString) return ""; // Remove whitespace between tags and collapse multiple spaces within attributes/text return svgString.replace(/>\s+</g, "><").replace(/\s\s+/g, " ").trim(); }; // --- Configuration: SVG Replacements (Normalized Original SVG HTML -> Replacement Image URL) --- const svgReplacements = { // Brazil / Marijampolė [normalizeSvgString( '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" xml:space="preserve"><path d="M0 0h512v512H0z" style="fill: rgb(109, 165, 68);"></path><path d="M256 114.527 448 256 256 397.473 64 256z" style="fill: rgb(255, 218, 68);"></path><circle cx="256" cy="256" r="80.84" style="fill: rgb(240, 240, 240);"></circle><path d="M215.579 250.948c-14.058 0-27.625 2.138-40.395 6.105.565 44.161 36.521 79.79 80.816 79.79 27.39 0 51.58-13.634 66.203-34.471-25.018-31.32-63.515-51.424-106.624-51.424zM335.343 271.488A81.137 81.137 0 0 0 336.842 256c0-44.648-36.194-80.843-80.843-80.843-33.314 0-61.913 20.156-74.29 48.935a166.852 166.852 0 0 1 33.869-3.46c46.957 0 89.433 19.517 119.765 50.856z" style="fill: rgb(0, 82, 180);"></path></svg>', )]: "https://upload.wikimedia.org/wikipedia/commons/a/ad/Marijampole_COA.svg", // Israel / Utena [normalizeSvgString( '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" xml:space="preserve"><path d="M0 0h512v512H0z" style="fill: rgb(240, 240, 240);"></path><path d="M352 200.575h-64.001L256 145.15l-31.998 55.425H160L192.002 256 160 311.425h64.002L256 366.85l31.999-55.425H352L319.998 256 352 200.575zM295.314 256l-19.656 34.048h-39.314L216.686 256l19.657-34.048h39.314L295.314 256zM256 187.903l7.316 12.672h-14.63L256 187.903zm-58.972 34.049h14.632l-7.316 12.672-7.316-12.672zm0 68.096 7.317-12.672 7.316 12.672h-14.633zM256 324.097l-7.315-12.672h14.63L256 324.097zm58.972-34.049H300.34l7.317-12.672 7.315 12.672zm-14.632-68.096h14.632l-7.316 12.672-7.316-12.672zM0 32h512v64H0zM0 416h512v64H0z" style="fill: rgb(0, 82, 180);"></path></svg>', )]: "https://upload.wikimedia.org/wikipedia/commons/a/ac/Coat_of_arms_of_Utena_(Lithuania).svg", // Italy / Alytus [normalizeSvgString( '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" xml:space="preserve"><path d="M341.334 0H0v512h512V0z" style="fill: rgb(240, 240, 240);"></path><path d="M0 0h170.663v512H0z" style="fill: rgb(109, 165, 68);"></path><path d="M341.337 0H512v512H341.337z" style="fill: rgb(216, 0, 39);"></path></svg>', )]: "https://upload.wikimedia.org/wikipedia/commons/d/d4/Coat_of_arms_of_Alytus_(Lithuania).svg", // Germany / Panevėžys [normalizeSvgString( '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" xml:space="preserve"><path d="M0 0h512v512H0z" style="fill: rgb(216, 0, 39);"></path><path d="M0 0h512v170.663H0z"></path><path d="M0 341.337h512V512H0z" style="fill: rgb(255, 218, 68);"></path></svg>', )]: "https://upload.wikimedia.org/wikipedia/commons/0/03/Coat_of_Arms_of_Panevezys.svg", // China / Šiauliai [normalizeSvgString( '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" xml:space="preserve"><path d="M0 0h512v512H0z" style="fill: rgb(216, 0, 39);"></path><path d="m167.619 167.43 19.541 60.143h63.239l-51.161 37.171 19.542 60.143-51.161-37.17-51.162 37.17 19.542-60.143-51.162-37.171h63.239zM290.787 367.465l-19.187-13.94-19.184 13.939 7.327-22.553-19.185-13.94h23.716l7.326-22.553 7.331 22.553h23.713l-19.185 13.939zM340.837 298.576h-23.714l-7.329 22.554-7.327-22.553-23.716-.001 19.187-13.94-7.329-22.552 19.187 13.937 19.185-13.938-7.329 22.553zM340.837 213.426l-19.185 13.94 7.328 22.551-19.184-13.936-19.187 13.938 7.329-22.555-19.186-13.938 23.715-.001 7.329-22.555 7.327 22.555zM290.787 144.536l-7.327 22.555 19.184 13.938-23.712.001-7.33 22.556-7.328-22.557-23.714.002 19.185-13.941-7.329-22.555 19.184 13.941z" style="fill: rgb(255, 218, 68);"></path></svg>', )]: "https://upload.wikimedia.org/wikipedia/commons/c/c8/Šiauliai_COA_small.svg", // France / Klaipėda [normalizeSvgString( '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" xml:space="preserve"><path d="M0 0h512v512H0z" style="fill: rgb(240, 240, 240);"></path><path d="M0 0h170.663v512H0z" style="fill: rgb(0, 82, 180);"></path><path d="M341.337 0H512v512H341.337z" style="fill: rgb(216, 0, 39);"></path></svg>', )]: "https://upload.wikimedia.org/wikipedia/commons/4/49/Coat_of_arms_of_Klaipeda_(Lithuania).svg", // United Kingdom / Kaunas [normalizeSvgString( '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" xml:space="preserve"><path d="M0 0h512v512H0z" style="fill: rgb(240, 240, 240);"></path><path d="M0 304h208v208h96V304h208v-96H304V0h-96v208H0z" style="fill: rgb(216, 0, 39);"></path><path d="M406.92 333.913 512 438.993v-105.08zM333.913 333.913 512 512v-50.36L384.273 333.913zM464.564 512 333.913 381.336V512z" style="fill: rgb(0, 82, 180);"></path><path d="M333.913 333.913 512 512v-50.36L384.273 333.913z" style="fill: rgb(240, 240, 240);"></path><path d="M333.913 333.913 512 512v-50.36L384.273 333.913z" style="fill: rgb(216, 0, 39);"></path><path d="M80.302 333.913 0 414.215v-80.302zM178.084 356.559v155.438H22.658z" style="fill: rgb(0, 82, 180);"></path><path d="M127.724 333.916 0 461.641V512l178.084-178.084z" style="fill: rgb(216, 0, 39);"></path><path d="M105.08 178.087 0 73.007v105.08zM178.087 178.087 0 0v50.36l127.727 127.727zM47.436 0l130.651 130.663V0z" style="fill: rgb(0, 82, 180);"></path><path d="M178.087 178.087 0 0v50.36l127.727 127.727z" style="fill: rgb(240, 240, 240);"></path><path d="M178.087 178.087 0 0v50.36l127.727 127.727z" style="fill: rgb(216, 0, 39);"></path><path d="M431.698 178.087 512 97.785v80.302zM333.916 155.441V.003h155.426z" style="fill: rgb(0, 82, 180);"></path><path d="M384.276 178.084 512 50.359V0L333.916 178.084z" style="fill: rgb(216, 0, 39);"></path></svg>', )]: "https://upload.wikimedia.org/wikipedia/commons/3/33/Coat_of_arms_of_Kaunas.svg", // USA / Vilnius [normalizeSvgString( '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" xml:space="preserve"><path d="M0 0h512v512H0z" style="fill: rgb(240, 240, 240);"></path><path d="M0 64h512v64H0zM0 192h512v64H0zM0 320h512v64H0zM0 448h512v64H0z" style="fill: rgb(216, 0, 39);"></path><path d="M0 0h256v275.69H0z" style="fill: rgb(46, 82, 178);"></path><path d="m51.518 115.318-5.594 17.211H27.826l14.643 10.634-5.594 17.212 14.643-10.634 14.637 10.634-5.595-17.212 14.643-10.634H57.106zM57.106 194.645l-5.588-17.211-5.594 17.211H27.826l14.643 10.634-5.594 17.211 14.643-10.633 14.637 10.633-5.595-17.211 14.643-10.634zM51.518 53.202l-5.594 17.212H27.826l14.643 10.633-5.594 17.212 14.643-10.634 14.637 10.634-5.595-17.212 14.643-10.633H57.106zM128.003 115.318l-5.594 17.211h-18.098l14.643 10.634-5.594 17.212 14.643-10.634 14.637 10.634-5.595-17.212 14.644-10.634h-18.098zM133.591 194.645l-5.588-17.211-5.594 17.211h-18.098l14.643 10.634-5.594 17.211 14.643-10.633 14.637 10.633-5.595-17.211 14.644-10.634zM210.076 194.645l-5.587-17.211-5.595 17.211h-18.097l14.643 10.634-5.595 17.211 14.644-10.633 14.636 10.633-5.594-17.211 14.643-10.634zM204.489 115.318l-5.595 17.211h-18.097l14.643 10.634-5.595 17.212 14.644-10.634 14.636 10.634-5.594-17.212 14.643-10.634h-18.098zM128.003 53.202l-5.594 17.212h-18.098l14.643 10.633-5.594 17.212 14.643-10.634 14.637 10.634-5.595-17.212 14.644-10.633h-18.098zM204.489 53.202l-5.595 17.212h-18.097l14.643 10.633-5.595 17.212 14.644-10.634 14.636 10.634-5.594-17.212 14.643-10.633h-18.098z" style="fill: rgb(240, 240, 240);"></path></svg>', )]: "https://upload.wikimedia.org/wikipedia/commons/e/e2/Coat_of_Arms_of_Vilnius.svg", }; // --- Core Logic --- // Helper to safely escape strings for regex creation function escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Pre-compile regex for text replacements for efficiency const textRegexMap = Object.entries(textReplacements).map( ([oldName, newName]) => ({ regex: new RegExp("\\b" + escapeRegExp(oldName) + "\\b", "gi"), newName: newName, }), ); // Processes a text node, replacing content based on textRegexMap function processTextNode(node) { let text = node.nodeValue; let originalText = text; textRegexMap.forEach((item) => { text = text.replace(item.regex, item.newName); }); if (text !== originalText) { node.nodeValue = text; // Update only if changes occurred } } // Replaces an SVG element with an IMG if its normalized HTML matches a key in svgReplacements function replaceMatchingSvg(svgElement) { if ( !svgElement || typeof svgElement.outerHTML !== "string" || !svgElement.parentNode ) { return false; // Requires a valid SVG element with a parent } const normalizedOuterHTML = normalizeSvgString(svgElement.outerHTML); const replacementUrl = svgReplacements[normalizedOuterHTML]; if (replacementUrl) { const img = document.createElement("img"); img.src = replacementUrl; // --- Sizing Logic --- // 1. Copy class from SVG: Essential for inheriting existing CSS sizing rules. if (svgElement.hasAttribute("class")) { img.setAttribute("class", svgElement.getAttribute("class")); } // 2. Apply inline styles for container fitting and aspect ratio preservation. // Acts as fallback if CSS doesn't specify dimensions. img.style.display = window.getComputedStyle(svgElement).display || "inline-block"; // Maintain display type img.style.width = "100%"; // Attempt to fill parent width img.style.height = "100%"; // Attempt to fill parent height img.style.objectFit = "contain"; // Scale down to fit, preserving aspect ratio // 3. Remove explicit width/height attributes to avoid overriding CSS/style rules. img.removeAttribute("width"); img.removeAttribute("height"); // --- End Sizing Logic --- // Add title/alt attributes derived from the image filename let title = "Lithuanian COA"; // Default title try { const urlParts = replacementUrl.split("/"); const filename = decodeURIComponent(urlParts[urlParts.length - 1]) // Handle encoded chars .replace(/\.(svg|png|jpg|jpeg|gif)$/i, "") // Remove extension .replace(/[_\-]/g, " ") // Replace underscores/hyphens with spaces .replace(/Coat of arms of /i, "") // Remove common prefixes .replace(/COA/i, "") .trim(); // Basic capitalization title = filename .split(" ") .map( (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(), ) .join(" ") .trim() || title; } catch (e) { console.warn( "Richup.io Replacer: Could not derive title from URL:", replacementUrl, e, ); } img.setAttribute("title", title); img.setAttribute("alt", title); // Use the same for alt text // Perform the replacement svgElement.parentNode.replaceChild(img, svgElement); return true; // Indicate replacement occurred } return false; // No matching replacement found } // Recursively walks the DOM, applying text and SVG processing functions function walkDOM(node, processTextFunc, processSvgFunc) { const tagName = node.tagName ? node.tagName.toUpperCase() : null; // Skip processing children of certain tags for performance and correctness if ( tagName === "SCRIPT" || tagName === "STYLE" || tagName === "TEXTAREA" || tagName === "INPUT" || tagName === "IMG" ) { return; } let nodeReplaced = false; if (node.nodeType === Node.ELEMENT_NODE) { // Attempt SVG replacement first for element nodes if (tagName === "SVG") { nodeReplaced = processSvgFunc(node); } // If the node itself wasn't replaced (e.g., it wasn't a matching SVG), process its children if (!nodeReplaced && node.childNodes) { // Iterate backwards because node list might be live or child replacement could affect indices for (let i = node.childNodes.length - 1; i >= 0; i--) { walkDOM(node.childNodes[i], processTextFunc, processSvgFunc); } } } else if (node.nodeType === Node.TEXT_NODE) { // Process non-empty text nodes if (node.nodeValue && node.nodeValue.trim() !== "") { processTextFunc(node); } } } const observerCallback = function (mutationsList) { for (const mutation of mutationsList) { if (mutation.type === "childList") { // Process newly added nodes mutation.addedNodes.forEach((addedNode) => { // Check if the added node itself needs processing or walk its subtree if ( addedNode.nodeType === Node.ELEMENT_NODE || addedNode.nodeType === Node.TEXT_NODE ) { walkDOM(addedNode, processTextNode, replaceMatchingSvg); } }); } else if (mutation.type === "characterData") { // Process text changes directly on the target node if (mutation.target.nodeType === Node.TEXT_NODE) { processTextNode(mutation.target); } } } }; // --- Initialization --- const observer = new MutationObserver(observerCallback); const observerConfig = { childList: true, // Watch for addition/removal of nodes subtree: true, // Watch descendants as well characterData: true, // Watch for changes to text nodes }; requestAnimationFrame(() => { try { // Start observing the document body for changes observer.observe(document.body, observerConfig); } catch (e) { console.error("Richup.io Replacer: Failed to start MutationObserver.", e); } }); // Perform an initial scan after a short delay to catch elements present on load // The observer will catch dynamically loaded elements afterwards. setTimeout(() => { console.log("Richup.io Replacer: Performing initial content scan..."); try { walkDOM(document.body, processTextNode, replaceMatchingSvg); console.log( "Richup.io Replacer: Initial scan complete. Observer active.", ); } catch (e) { console.error("Richup.io Replacer: Error during initial scan.", e); } }, 500); })();