GeoGuessr Custom Maps

using modified maps in geoguessr games

Version au 15/08/2024. Voir la dernière version.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

You will need to install an extension such as Tampermonkey to install this script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         GeoGuessr Custom Maps
// @namespace    https://greasyfork.org/users/1179204
// @description  using modified maps in geoguessr games
// @version      1.0.5
// @author       KaKa
// @license      BSD
// @match        *://www.geoguessr.com/*
// @require      https://update.greasyfork.org/scripts/502813/1423193/Geoguessr%20Tag.js
// @icon         https://www.svgrepo.com/show/392367/interaction-interface-layer-layers-location-map.svg

// ==/UserScript==

(function() {

    /*=========================================================================Modifiy your guess map here==================================================================================*/

    let customOptions={

        Language:'en',                                  //en,zh,ja,fr,de,es

        Google_StreetView_Layer_Lines_Style:'Default',   // More styles see below

        Google_StreetView_Layer_Shortcut:'V',

        Google_Labels_Layer_Shortcut:'G',

        Google_Terrain_Layer_Shortcut:'T',

        Google_Satellite_Layer_Shortcut:'B',

        OpenWeather_Shortcut:'Q',

        OpenWeather_Style:'radar',                      //'radar': Global Precipitation;  'CL':Cloud;  'APM':Pressure;  'TA2'Temperature;  'WS10':Wind Speed;

        OpenWeather_Date:'now',                        // foramt:yyyy-mm-dd, less than one week ago

        Bing_Maps_Style:'r',                           // 'a':satellite(without labels);  'h':hybrid;  'r':roadmap,'sre':terrain

        Map_Tiler_Style:'basic',                       //basic,satellite,bright,landscape,ocean,outdoor,topo,streets,dataviz

        Carto_Style:'light_all',                       //light_all,dark_all

        Thunderforest_Style:'spinal-map'}              //spinal-map,landscape,outdoors,atlas,transport,


    let tileServices=["Google_Maps","OpenStreetMap","Bing_Maps","Map_Tiler","Thunderforest","Carto","Petal_Maps"]

    let colorOptions={

        Default:['1098ad','99e9f2'],

        Crimson:['f03e3e','ffc9c9'],

        Deep_Pink:['d6336c','fcc2d7'],

        Blue_Violet:['ae3ec9','eebefa'],

        Slate_Blue:['7048e8','d0bfff'],

        Royal_Blue:['4263eb','bac8ff'],

        Dodger_Blue: ['1c7ed6','a5d8ff'],

        Sea_Green:['0ca678','96f2d7'],

        Lime_Green:['37b24d','b2f2bb'],

        OliveDrab:['74b816','d8f5a2'],

        Orange:['f59f00','ffec99'],

        Dark_Orange:['f76707','ffd8a8'],

        Brown:['bd5f1b','f7ca9e'],
    }

    /*======================================================================================================================================================================================*/


    let currentMapType='roadmap',currentLayers=[],isGoogleDisplay=true,isSV=false,opacityControl

    const openWeatherBaseURL = "https://g.sat.owm.io/vane/2.0/weather";
    const radarURL = `https://b.sat.owm.io/maps/2.0/radar/{z}/{x}/{y}?appid=9de243494c0b295cca9337e1e96b00e2&day=${getNow(customOptions.OpenWeather_Date)}`;

    const openWeatherURL = (customOptions.OpenWeather_Style === 'radar')
    ? radarURL
    : `${openWeatherBaseURL}/${customOptions.OpenWeather_Style}/{z}/{x}/{y}?appid=9de243494c0b295cca9337e1e96b00e2&&date=${getTimestamp(customOptions.OpenWeather_Date)}&fill_bound=true`;

    let tileUrls = {
        Petal_Maps: `https://maprastertile-dre.dbankcdn.com/display-service/v1/online-render/getTile/24.07.06.10/{z}/{x}/{y}/?language=${customOptions.Language}&p=46&scale=1&mapType=ROADMAP&presetStyleId=standard&key=CgB6e3x91JxUZ4Ow3JZYVG6r9c9U7rH4ameNQdauHVaVBYGWwy8ueadAtqjs6Yl2z3OwymAEx3JR83vpgPzv4nuC`,
        OpenStreetMap: "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
        Map_Tiler:`https://api.maptiler.com/maps/${customOptions.Map_Tiler_Style}-v2/256/{z}/{x}/{y}.png?key=0epLOAjD7fw17tghcyee`,
        Thunderforest:`https://a.tile.thunderforest.com/${customOptions.Thunderforest_Style}/{z}/{x}/{y}@2x.png?apikey=6a53e8b25d114a5e9216df5bf9b5e9c8`,
        Carto:`https://cartodb-basemaps-3.global.ssl.fastly.net/${customOptions.Carto_Style}/{z}/{x}/{y}.png`,
        Google_StreetView:`https://maps.googleapis.com/maps/vt?pb=%211m5%211m4%211i{z}%212i{x}%213i{y}%214i256%212m8%211e2%212ssvv%214m2%211scc%212s*211m3*211e2*212b1*213e2*212b1*214b1%214m2%211ssvl%212s*212b1%213m17%212sen%213sUS%215e18%2112m4%211e68%212m2%211sset%212sRoadmap%2112m3%211e37%212m1%211ssmartmaps%2112m4%211e26%212m2%211sstyles%212ss.e%3Ag.f%7Cp.c%3A%23${colorOptions[customOptions.Google_StreetView_Layer_Lines_Style][0]}%7Cp.w%3A1%2Cs.e%3Ag.s%7Cp.c%3A%23${colorOptions[customOptions.Google_StreetView_Layer_Lines_Style][1]}%7Cp.w%3A3%215m1%215f1.35`,
        Google_Labels:`https://maps.googleapis.com/maps/vt?pb=!1m5!1m4!1i{z}!2i{x}!3i{y}!4i256!2m1!2sm!3m17!2s${customOptions.Language}!3sUS!5e18!12m4!1e68!2m2!1sset!2sRoadmap!12m3!1e37!2m1!1ssmartmaps!12m4!1e26!2m2!1sstyles!2ss.e:g|p.v:off,s.t:1|s.e:g.s|p.v:off,s.e:l|p.v:on!5m1!5f2`,
        OpenWeather: openWeatherURL
    }

    let map,google,gsvLayer,initLayer=tag
    
    setTimeout(function(){
        getMap()
    },2000);
    initCustomizer()

    function createOpacityControl(controlDiv, layer) {
        controlDiv.style.margin='20px'
        controlDiv.style.backgroundColor = '#fff';
        controlDiv.style.height = '30px';
        controlDiv.style.boxShadow = 'rgba(0, 0, 0, 0.3) 0px 1px 4px -1px';
        controlDiv.style.borderRadius = '5px';

        var opacitySlider = document.createElement('input');

        opacitySlider.setAttribute('type', 'range');
        opacitySlider.setAttribute('id', 'timeRange');
        opacitySlider.setAttribute('min', '0');
        opacitySlider.setAttribute('max', '100');
        opacitySlider.setAttribute('value', '100');
        opacitySlider.setAttribute('step', '1');
        opacitySlider.style.width = '80px';
        opacitySlider.style.height='20px'
        opacitySlider.style.marginTop='5px'
        opacitySlider.addEventListener('input', function() {
            var opacity = opacitySlider.value / 100
            layer.setOpacity(opacity);

        });

        controlDiv.appendChild(opacitySlider);
    }

    function addOpacityControl(m, layer) {
        var opacityControlDiv = document.createElement('div');
        new createOpacityControl(opacityControlDiv, layer);
        opacityControl =true
        opacityControlDiv.index = 1;
        m.controls[google.maps.ControlPosition.TOP_RIGHT].push(opacityControlDiv);
    }

    function removeOpacityControl(){
        if(opacityControl){
            map.controls[google.maps.ControlPosition.TOP_RIGHT].removeAt(map.controls[google.maps.ControlPosition.TOP_RIGHT].getLength() - 1)
            opacityControl=false
        }
    }

    function getNow(date) {
        if(date!='now'){
            return date
        }
        const now = new Date();
        now.setHours(now.getHours() - 1);
        return now.toISOString().slice(0, 14)+'00';
    }

    function getTimestamp(date){
        var parsedDate
        if (date=== 'now') {
            parsedDate= new Date()
             return Math.floor(parsedDate.getTime() / 1000)
        }
        parsedDate = new Date(date);

        if (isNaN(parsedDate.getTime())) {
            throw new Error('Invalid date format');
        }
        return Math.floor(parsedDate.getTime() / 1000);

    }

    function extractTileCoordinates(url) {
        const regex = /!1i(\d+)!2i(\d+)!3i(\d+)!4i(\d+)/;
        const matches = url.match(regex);

        if (matches && matches.length === 5) {
            const z = matches[1];
            const x = matches[2];
            const y = matches[3];
            return { z, x, y };
        } else {
            return null;
        }
    }
    function getBingTiles(tileX, tileY, zoom,type) {
        var quadKey = tileXYToQuadKey(tileX, tileY, zoom);
        var baseUrl = 'https://ecn.t0.tiles.virtualearth.net/tiles/';

        return baseUrl + type + quadKey + '.jpeg?g=14519';
    }
    function tileXYToQuadKey(tileX, tileY, zoom) {
        var quadKey = '';
        for (var i = zoom; i > 0; i--) {
            var digit = 0;
            var mask = 1 << (i - 1);
            if ((tileX & mask) !== 0) {
                digit += 1;
            }
            if ((tileY & mask) !== 0) {
                digit += 2;
            }
            quadKey += digit.toString();
        }
        return quadKey;
    }


    function setMapLayer(layerName) {
        var tileLayerUrl = tileUrls[layerName];
        var tileLayer
        if (layerName==='Bing_Maps') {
            tileLayer = new google.maps.ImageMapType({
                getTileUrl: function(coord, zoom) {
                    return getBingTiles(coord.x,coord.y,zoom,customOptions.Bing_Maps_Style)
                        .replace('{z}', zoom)
                        .replace('{x}', coord.x)
                        .replace('{y}', coord.y);
                },
                tileSize: new google.maps.Size(256, 256),
                name: layerName
            });
        }
        else{
            tileLayer = new google.maps.ImageMapType({
                getTileUrl: function(coord, zoom) {
                    return tileLayerUrl
                        .replace('{z}', zoom)
                        .replace('{x}', coord.x)
                        .replace('{y}', coord.y);
                },
                tileSize: new google.maps.Size(256, 256),
                name: layerName
            });
        }

        if(!layerName.includes('Google')){
            isGoogleDisplay=false
        }
        if(currentLayers.includes(layerName)){
            removeMapLayer(layerName)
            const index = currentLayers.indexOf(layerName);
            if (index !== -1) {
                currentLayers.splice(index, 1);
            }
            if(!layerName.includes(('Google')||('Weather'))){
                map.overlayMapTypes.clear();
                currentLayers=[]
                isGoogleDisplay=true
                setMapLayer('Google_Labels')
            }
        }
        else {
            map.overlayMapTypes.push(tileLayer)
            currentLayers.push(layerName)};

        if(layerName==='Google_StreetView'){
            if (!opacityControl){
                addOpacityControl(map,tileLayer)}
            else {
                removeOpacityControl()
            }
        }
    }


    function removeMapLayer(layerName) {
        for (let i = 0; i < map.overlayMapTypes.getLength(); i++) {
            const currentLayer = map.overlayMapTypes.getAt(i);
            if (currentLayer && currentLayer.name === layerName) {
                map.overlayMapTypes.removeAt(i);
                break;
            }
        }
    }

    function getMap(){
        let element = document.getElementsByClassName("guess-map_canvas__cvpqv")[0]
        //if (!element) element=document.getElementsByClassName("coordinate-result-map_map__Yh2Il")[0]
        const keys = Object.keys(element)
        const key = keys.find(key => key.startsWith("__reactFiber$"))
        const props = element[key]
        map=props.return.return.memoizedProps.map
        google=unsafeWindow.google
    }

    function setMapType(customType){
        if (currentMapType!=customType){
            currentMapType=customType
        }
        else{
            currentMapType='roadmap'
        }
        map.setMapTypeId(currentMapType);
    }


    function initCustomizer(){
        let onKeyDown = (e) => {
            if (e.key >= '1' && e.key <= '6') {
                e.stopImmediatePropagation();
                if(!map) getMap()
                const tileIndex=parseInt(e.key)
                initLayer(`layer:${tileServices[tileIndex]}`)
                map.overlayMapTypes.clear();
                currentLayers=[]
                removeOpacityControl()
                setMapLayer(tileServices[tileIndex])
            }
            else if (e.key === '0') {
                e.stopImmediatePropagation();
                if(!map) getMap()
                initLayer('layer:Google_Labels')
                map.overlayMapTypes.clear();
                currentLayers=[]
                isGoogleDisplay=true
                removeOpacityControl()
                map.set('styles', [
                    {
                        featureType: 'all',
                        elementType: 'labels',
                        stylers: [{ visibility: 'on' }]
                    }
                ])
                isSV=false
            }
            else if (e.key === customOptions.Google_StreetView_Layer_Shortcut.toLowerCase()|| e.key === customOptions.Google_StreetView_Layer_Shortcut) {
                e.stopImmediatePropagation();
                if(!map) getMap()
                initLayer('layer:Google_StreetView')
                if(!isSV){
                    map.set('styles', [
                        {
                            featureType: 'all',
                            elementType: 'labels',
                            stylers: [{ visibility: 'off' }]
                        }
                    ])
                    isSV=true}
                else{
                    map.set('styles', [
                        {
                            featureType: 'all',
                            elementType: 'labels',
                            stylers: [{ visibility: 'on' }]
                        }
                    ])
                    isSV=false
                }
                setMapLayer('Google_StreetView')
                if (isGoogleDisplay)setMapLayer('Google_Labels')
            }
            else if (e.key === customOptions.Google_Labels_Layer_Shortcut.toLowerCase()|| e.key === customOptions.Google_Labels_Layer_Shortcut) {
                e.stopImmediatePropagation();
                if(!map) getMap()
                initLayer('layer:Google_Labels')
                if(isSV){
                    setMapLayer('Google_Labels')}
            }
            else if (e.key === customOptions.Google_Terrain_Layer_Shortcut.toLowerCase()|| e.key === customOptions.Google_Terrain_Layer_Shortcut) {
                e.stopImmediatePropagation();
                if(!map) getMap()
                initLayer('layer:terrain')
                setMapType('terrain')
            }
            else if (e.key === customOptions.Google_Satellite_Layer_Shortcut.toLowerCase()|| e.key === customOptions.Google_Satellite_Layer_Shortcut) {
                e.stopImmediatePropagation();
                if(!map) getMap()
                initLayer('layer:satellite')
                setMapType('satellite')
            }
            else if (e.key === customOptions.OpenWeather_Shortcut.toLowerCase()|| e.key === customOptions.OpenWeather_Shortcut) {
                e.stopImmediatePropagation();
                if(!map) getMap()
                initLayer('layer:weather')
                setMapLayer('OpenWeather')
            }
        }

        document.addEventListener("keydown", onKeyDown);
    }

})();