HaxBall Map Picker

Load and Save maps from haxmaps just using an ID.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 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...
})();