HaxBall Map Picker

Load and Save maps from haxmaps just using an ID.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         HaxBall Map Picker
// @namespace    https://greasyfork.org/en/users/165127-hydrosaur
// @version      3.0
// @icon         https://www.haxball.com/favicon.ico
// @description  Load and Save maps from haxmaps just using an ID.
// @author       -Electron-
// @include      https://www.haxball.com/FFuuq69i/__cache_static__/g/game.html
// @supportURL   https://www.reddit.com/message/compose/?to=-Electron-
// @website      https://redd.it/no-post-yet
// @require      https://code.jquery.com/jquery-latest.min.js
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    let pickerPopupIsShown = false;
    let gamePageIsShown = false;

    let haxMap = 0;

    let favoritesListShown = false;

    if(!localStorage.getItem("saved_maps")){
        localStorage.setItem("saved_maps", "{}");
    }

    setInterval(function(){
        if($(".dialog.pick-stadium-view").length){
            if(!pickerPopupIsShown) showPicker();
            pickerPopupIsShown = true;
        } else {
            if(pickerPopupIsShown) hidePicker();
            pickerPopupIsShown = false;
        }

        if($("button[data-hook='leave-btn']").length){
            if(!gamePageIsShown) gamePageShown();
            gamePageIsShown = true;
        } else {
            if(gamePageIsShown) gamePageHidden();
            gamePageIsShown = false;
        }
    }, 250);

    function showPicker(){
        $(".dialog.pick-stadium-view h1").eq(0).append("<img class='loader' style='display: none' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAAIqSURBVDhPdVM9rCFRFB4FeaJQ0ChVEiT7si0iopBotbQUgqh0FKIVPxlvRSEhEXpR7q4NkQiVzXuLRCK6jUTjvWXunTt7zuyY4L39ki8zc+45537nZ7gP8Nnn8/HZbPalVCq9FYvFUygUegH7FzyTPf4DPbAeDocJY0y6RzweF3ieF91u95PiewM0/ABKcKugxMiAZGy5XNJarSbbD4cDA0VfwfcBAy+oA6VAIEC73S6Fm874zGQy1Gq1inhms9nYfr+XpWESl8uFSmRgXSyRSFCAqr1QKAhgl67p9/vFi0+v1zuD7ZHzer18Op0W7uuu1+v0PgEyGo2Sfr9Pm80mge8nDrtdrVb/KHEqOp3OOwUajUaaTCZ0t9tRSIQXLDkc1UcJyuUyNZvNcv0XRiIRqhxL6/UaEwhyglgsRsbjMcUyRFFE+WQ2m4mEEDYcDin2x26300sTEdgLvV5/5uDwp06nY3iDw+GgyWRS2G63ouKnApNiQuVTOp1OzGAwPHNarZa/lgmdVmVeYzQa0cVioSZuNBqv4F8CwihgjBiMNBqNTBCE25EAVqsVTaVSZD6f0+l0SoLB4G/w/wSUgXuuqoAxESVOxmazEWGR1IZaLJY3WKQavKvAVf7udDpJLpejMEJSqVSEdrtNW60WMZlMqkKF34A3q4x4wPUcDAb4M8klHI9HEZp6vVC4PKj23c90jUePx8ODkmcccT6ff4UF+gV2lKzW/A8c9xdfxQlApF7TUgAAAABJRU5ErkJggg==' />");

        rotateForEver($(".dialog.pick-stadium-view h1 .loader"));

        $(`<button data-hook="favorites">Favorites</button>`).insertAfter(".dialog.pick-stadium-view .buttons .file-btn");
        $(`<button data-hook="haxmapid">HaxMapID</button>`).insertAfter(".dialog.pick-stadium-view .buttons .file-btn");
        $(`<button data-hook="searchmaps">Search</button>`).insertAfter(".dialog.pick-stadium-view .buttons .file-btn");
        $("button[data-hook='haxmapid']").click(function(){
            let mapID = prompt("Map ID:");

            if(!isNaN(Number(mapID)) && mapID){

                changeStadium(mapID);
            } else {
                alert("Invalid Map ID")
            }
        });

        $("button[data-hook='searchmaps']").click(function(){
            let mapSearch = prompt("Map Search:");

            if(mapSearch){
                $(".dialog.pick-stadium-view .loader").css("display", "inline");
                fetch("https://streamlyne.stream:88/haxmaps/" + encodeURIComponent(mapSearch)).then(a => a.json()).then(json => {
                    favoritesListShown = true;

                    $(".dialog.pick-stadium-view .list.ps").empty();

                    let savedMaps = json.maps;

                    savedMaps.forEach((item, idx) => {
                        $(".dialog.pick-stadium-view .list.ps").append(`<div class="elem" data-id="${item.id}">DLS:<b>${item.downloads}</b>|${item.name}</div>`);
                    });

                    $(".dialog.pick-stadium-view .list.ps .elem").click(function(){
                        $(".selected").removeClass("selected");
                        $(this).addClass("selected");
                        $("button[data-hook='pick']").prop("disabled", false);
                    });

                    $("button[data-hook='pick']").click(function(){
                        console.log("cliq");
                        if($(".dialog.pick-stadium-view .list.ps .selected").length){
                            if(!isNaN(Number($(".dialog.pick-stadium-view .list.ps .selected").attr("data-id")))){
                                changeStadium($(".dialog.pick-stadium-view .list.ps .selected").attr("data-id"));
                            }
                        }
                    });

                    $(".dialog.pick-stadium-view .loader").hide();
                }).catch(function(){
                    $(".dialog.pick-stadium-view .loader").hide();
                });
            }
        });

        $("button[data-hook='favorites']").click(function(){
            favoritesListShown = true;

            $(".dialog.pick-stadium-view .list.ps").empty();

            let savedMaps = JSON.parse(localStorage.getItem("saved_maps"));

            Object.keys(savedMaps).forEach((item, idx) => {
                $(".dialog.pick-stadium-view .list.ps").append(`<div class="elem" data-id="${savedMaps[item]}">${item}</div>`);
            });

            $(".dialog.pick-stadium-view .list.ps .elem").click(function(){
                $(".selected").removeClass("selected");
                $(this).addClass("selected");
                $("button[data-hook='pick']").prop("disabled", false);
            });

            $("button[data-hook='pick']").click(function(){
                console.log("cliq");
                if($(".dialog.pick-stadium-view .list.ps .selected").length){
                    if(!isNaN(Number($(".dialog.pick-stadium-view .list.ps .selected").attr("data-id")))){
                        changeStadium($(".dialog.pick-stadium-view .list.ps .selected").attr("data-id"));
                    }
                }
            });
        });
    }

    function hidePicker(){
        favoritesListShown = false;
    }

    function gamePageShown(){
        if(!$("button[data-hook='addfavorites']").length){
            $(".settings").append("<button class='admin-only' data-hook='addfavorites' style='width: 100%'>Add Map To Favorites</button>");

            $("button[data-hook='addfavorites']").click(function(){
                if(haxMap){
                    let saved_maps = JSON.parse(localStorage.getItem("saved_maps"));
                    let savedMapIDs = Object.values(saved_maps);

                    if(savedMapIDs.includes(Number(haxMap))){
                        alert("You have already saved this map.");
                    } else {
                        saved_maps[$("label[data-hook='stadium-name']").text()] = Number(haxMap);
                        localStorage.setItem("saved_maps", JSON.stringify(saved_maps));
                        alert("Saved " + $("label[data-hook='stadium-name']").text());
                    }
                } else {
                    alert("You can only favorite maps that are uploaded to haxmaps.com");
                }
            });
        }
    }

    function gamePageHidden(){

    }

    $("button[data-hook='pick']").click(function(){
        haxMap = 0;
    })

    function searchForMaps(query){
        fetch("https://streamlyne.stream:88/proxy?link=http://haxmaps.com/hb/rpc").then(a => a.text()).then(text => {
            let listElems = $(text);

            console.log(Array.from(listElems))
        });
    }

    function linkToBlob(link){
        return new Promise(function(resolve, reject) {
            let xhr = new XMLHttpRequest();
            xhr.open("GET", link);
            xhr.responseType = "blob";//force the HTTP response, response-type header to be blob
            xhr.onload = function(){
                resolve(xhr.response);
            }
            xhr.send();
        });
    }

    function getHaxBallMapText(id){
        return new Promise(function(resolve, reject) {
            fetch("https://streamlyne.stream:88/proxy?link=http://haxmaps.com/dl/" + id).then(a => a.text()).then(function(text){
                resolve(text);
            });
        });
    }

    function changeStadium(id){
        getHaxBallMapText(id).then(text => {
            if(text.length > 2){
                changeStadiumFromText(text);
                haxMap = Number(id);
            } else {
                alert("Map ID out of range");
            }
        });
    }

    function rotateForEver($elem, rotator) {
        if (rotator === void(0)) {
            rotator = $({deg: 0});
        } else {
            rotator.get(0).deg = 0;
        }

        return rotator.animate(
            {deg: 360},
            {
                duration: 5000,
                easing: 'linear',
                step: function(now){
                    $elem.css({transform: 'rotate(' + now + 'deg)'});
                },
                complete: function(){
                    rotateForEver($elem, rotator);
                },
            }
        );
    }

    function changeStadiumFromText(text){
        const dT = new ClipboardEvent('').clipboardData || // Firefox < 62 workaround exploiting https://bugzilla.mozilla.org/show_bug.cgi?id=1422655
              new DataTransfer(); // specs compliant (as of March 2018 only Chrome)
        dT.items.add(new File([text], 'programmatically_created.hbs'));
        console.log(text);
        document.getElementById("stadfile").files = dT.files;
    }

    // Your code here...
})();