Wplace Dark Mode

Dark mode do mapa sem sobrescrever window.fetch (não conflita com outros scripts).

// ==UserScript==
// @name        Wplace Dark Mode
// @namespace   awoone.scripts
// @match       https://wplace.live/*
// @grant       GM_addStyle
// @version     1.0.0
// @author      awo
// @description Dark mode do mapa sem sobrescrever window.fetch (não conflita com outros scripts).
// @run-at      document-start
// @license     MIT
// ==/UserScript==

(() => {
  "use strict";

  try {
    GM_addStyle(`
      :root {
        --color-base-100: #1b1e24;
        --color-base-200: #262b36;
        --color-base-300: #151922;
        --color-base-content: #f5f6f9;
        --noise: 0;
      }
      #color-0 { background-color: white !important; }
    `);
  } catch (_) {}

  const MAP_STYLE_URL = "https://maps.wplace.live/styles/liberty";
  const PATCH_FLAG = Symbol.for("wplace.darkmode.json.patched");

  if (!Response.prototype.json[PATCH_FLAG]) {
    const origJson = Response.prototype.json;

    function applyLibertyDarkTheme(styleObj) {
      try {
        if (!styleObj || !Array.isArray(styleObj.layers)) return styleObj;

        for (const layer of styleObj.layers) {
          if (!layer || typeof layer !== "object") continue;
          const p = layer.paint || (layer.paint = {});

          switch (layer.id) {
            case "background":
              p["background-color"] = "#272e40";
              break;
            case "water":
              p["fill-color"] = "#000d2a";
              break;
            case "waterway_tunnel":
            case "waterway_river":
            case "waterway_other":
              p["line-color"] = "#000d2a";
              break;
            case "natural_earth":
              p["raster-brightness-max"] = 0.4;
              break;
            case "landcover_ice":
              p["fill-color"] = "#475677";
              break;
            case "landcover_sand":
              p["fill-color"] = "#775f47";
              break;
            case "park":
              layer.paint = { "fill-color": "#0e4957", "fill-opacity": 0.7 };
              break;
            case "park_outline":
              p["line-opacity"] = 0;
              break;
            case "landuse_pitch":
            case "landuse_track":
            case "landuse_school":
              p["fill-color"] = "#3e4966";
              break;
            case "landuse_cemetery":
              p["fill-color"] = "#3b3b57";
              break;
            case "landuse_hospital":
              p["fill-color"] = "#663e3e";
              break;
            case "building":
              p["fill-color"] = "#1c3b69";
              break;
            case "building_3d":
              p["fill-extrusion-color"] = "#1c3b69";
              break;
            case "waterway_line_label":
            case "water_name_point_label":
            case "water_name_line_label":
              p["text-color"] = "#8bb6f8";
              p["text-halo-color"] = "rgba(0,0,0,0.7)";
              break;
            case "tunnel_path_pedestrian":
            case "road_path_pedestrian":
            case "bridge_path_pedestrian":
              p["line-color"] = "#7c8493";
              break;
            case "bridge_path_pedestrian_casing":
              p["line-color"] = "#3b4d65";
              break;
            case "road_minor":
            case "tunnel_service_track":
            case "tunnel_minor":
            case "road_service_track":
            case "bridge_service_track":
            case "bridge_street":
              p["line-color"] = "#3b4d65";
              break;
            case "tunnel_link":
            case "tunnel_secondary_tertiary":
            case "tunnel_trunk_primary":
            case "tunnel_motorway":
              p["line-color"] = "#4a627e";
              break;
            case "label_other":
            case "label_state":
              p["text-color"] = "#91a0b5";
              p["text-halo-color"] = "rgba(0,0,0,0.7)";
              break;
            case "poi_r20":
            case "poi_r7":
            case "poi_r1":
              p["text-color"] = "#91a0b5";
              p["text-halo-color"] = "rgba(0,0,0,0.7)";
              break;
            case "poi_transit":
            case "highway_name_path":
            case "highway_name_major":
              p["text-color"] = "#cde0fe";
              p["text-halo-color"] = "rgba(0,0,0,0.7)";
              break;
            case "highway_name_minor":
              p["text-color"] = "#91a0b5";
              p["text-halo-color"] = "rgba(0,0,0,0.7)";
              break;
            case "label_village":
            case "label_town":
            case "label_city":
            case "label_city_capital":
            case "label_country_3":
            case "label_country_2":
            case "label_country_1":
              p["text-color"] = "#e4e5e9";
              p["text-halo-color"] = "rgba(0,0,0,0.7)";
              break;
            case "airport":
              p["text-color"] = "#92b7fe";
              p["text-halo-color"] = "rgba(0,0,0,0.7)";
              break;
            case "aeroway_fill":
              p["fill-color"] = "#2a486c";
              break;
            case "aeroway_runway":
              p["line-color"] = "#253d61";
              break;
            case "aeroway_taxiway":
              p["line-color"] = "#3d5b77";
              break;
            case "boundary_3":
              p["line-color"] = "#707784";
              break;
          }
        }

        const replacements = new Map([
          ["#e9ac77", "#476889"],
          ["#fc8", "#476889"],
          ["#fea", "#3d5b77"],
          ["#cfcdca", "#3b4d65"],
        ]);

        const seen = new WeakSet();
        (function walk(obj) {
          if (!obj || typeof obj !== "object" || seen.has(obj)) return;
          seen.add(obj);
          for (const k of Object.keys(obj)) {
            const v = obj[k];
            if (typeof v === "string") {
              if (replacements.has(v)) obj[k] = replacements.get(v);
            } else if (v && typeof v === "object") {
              walk(v);
            }
          }
        })(styleObj);

        return styleObj;
      } catch (e) {
        return styleObj;
      }
    }

    Object.defineProperty(Response.prototype, "json", {
      configurable: true,
      enumerable: false,
      writable: true,
      value: async function patchedJson() {
        const data = await origJson.call(this);
        try {
          if (typeof this.url === "string" && this.url === MAP_STYLE_URL) {
            return applyLibertyDarkTheme(data);
          }
        } catch (_) {}
        return data;
      },
    });

    Response.prototype.json[PATCH_FLAG] = true;
  }
})();