Greasy Fork is available in English.

Florr.io Take High Quality ScreenShots & Lower the Lag!

Take screenshots with the desired quality in florr.io! (You may need to manually resize your browser's window if the quality hasn't changed by itself), automatically take a screenshot if your score is over a custom number and pause/play the game to seek a perfect screenshot

// ==UserScript==
// @name         Florr.io Take High Quality ScreenShots & Lower the Lag!
// @version      2.3
// @description  Take screenshots with the desired quality in florr.io! (You may need to manually resize your browser's window if the quality hasn't changed by itself), automatically take a screenshot if your score is over a custom number and pause/play the game to seek a perfect screenshot
// @author       woold#2808
// @match        https://florr.io/*
// @run-at       document-start
// @grant		 unsafeWindow
// @grant		 GM_addStyle
// @namespace https://greasyfork.org/users/452524
// ==/UserScript==

var gameScene = "menu";
var autoDeaSS = localStorage.autoDeaSS || true;
var dopeScore = !!localStorage.dopeScore? Number(localStorage.dopeScore) : 22400;
var inners = [`<p>•Press ${gameScene == "menu"?"[CTRL]+":""}[I] to take a screenshot</p>`,`<p>•Press ${gameScene == "menu"?"[CTRL]+":""}[U] to change the game's and screenshot's quality (${unsafeWindow.devicePixelRatio})</p>`,`<p>•Press ${gameScene == "menu"? !paused?"[CTRL]+[H] to pause the game to seek a perfect screenshot!":"[H] to play back the game":!paused?"[H] to pause the game to seek a perfect screenshot!":"[H] to play back the game"}</p>`,`<p>•Press ${gameScene == "menu"?"[CTRL]+":""}[O] to ${autoDeaSS?"disable":"enable"} auto screenshot on death if your score is over ${correctToSigFig(dopeScore)} (${autoDeaSS?"ON":"OFF"})</p>`]
var innerids = ["SSBanner","qualityBanner","pauseBanner","autoDeaSSBanner"];
var paused = false;
var curPoints = 0;
var hasMenuDisp = false;

const WebSocketProxy = new Proxy(unsafeWindow.WebSocket, {
    set: (target, key, value) => {
        return true;
    },
    get: (target, key) => {
        if (key !== "__isProxy") {
            return target[key];
        }

        return true;
    },

    construct(target, args) {
        if (args[0] === 'noProxy') {
            if (target.__isProxy) {
                return Reflect.construct(target, args);
            } else {
                return Reflect.construct(target, args.slice(1));
            }
        }

        const instance = Reflect.construct(...arguments);

        const instanceProxy = new Proxy(instance.send, {
            apply(target, thisArg, args) {
                if (args[0] instanceof Int8Array && args[0][0] === 1) {
                    if (args[0].length === 11) {
                        const array1 = [...args[0].slice(3, 11)];
                        const array2 = new Array(8).fill(0);
                        if (!array1.every((value, index) => value === array2[index]) && gameScene == "menu") {
                            gameScene = "playing";
                            updateElems();
                        }
                    } else if (args[0].length == 2 && args[0].every((value, index) => value === [1,0][index])) {
                        gameScene = "menu";
                        updateElems();
                    }
                }

                return Reflect.apply(...arguments);
            }
        });

        instance.send = instanceProxy;

        instance.addEventListener("close", function() {
            gameScene = "menu";
            updateElems();
        })

        return instance;
    }
});

unsafeWindow.WebSocket = WebSocketProxy;

const CVS = !!unsafeWindow.OffscreenCanvasRenderingContext2D?"OffscreenCanvasRenderingContext2D":!!unsafeWindow.CanvasRenderingContext2D?"CanvasRenderingContext2D":"";

if (!!CVS) {
    const fillTextProxy = new Proxy(unsafeWindow[CVS].prototype.fillText, {
        set: (target, key, value) => {
            return true;
        },
        get: (target, key) => {
            if (key !== "__isProxy") {
                return target[key];
            }

            return true;
        },
        apply(target, thisArg, args) {
            if (args[0] === 'noProxy') {
                if (target.__isProxy) {
                    return Reflect.apply(target, thisArg, args);
                } else {
                    return Reflect.apply(target, thisArg, args.slice(1));
                }
            }
            if (!args[0].includes("-")) {
                if (args[0].includes("Lvl ") && args[0].includes(" Flower") && gameScene == "menu") {
                    gameScene = "playing";
                    updateElems();
                } else if (args[0].includes("Points: ") && args[0] != "Points: 0" && gameScene == "playing") {
                    gameScene = "death";
                    updateElems();
                    if (args[0].includes("Points: ")) {
                        curPoints = args[0].replace("Points: ","");
                    }
                    if (autoDeaSS && Number(correctToSigFig(curPoints,true)) >= Number(dopeScore)) {
                        var dataURL;
                        setTimeout(function(){
                            if (gameScene == "death") {
                                dataURL = k.canvas.toDataURL("image/png", 1.0);
                            }
                            setTimeout(function(){
                                if (gameScene == "death") {
                                    dataURL = k.canvas.toDataURL("image/png", 1.0);
                                }
                                downloadImage(dataURL, (localStorage.florrio_nickname||"Unnamed Flower")+' ('+curPoints+' of score) - florr.io.png');
                            },750)
                        },750)
                    }
                }
            }
            return Reflect.apply(...arguments);
        }
    });
    unsafeWindow[CVS].prototype.fillText = fillTextProxy;
} else {
   alert(`Your browser doesn't support this script, try switching to Chrome or Firefox or uninstall the script nammed "${GM_info.script.name}"`)
}

var pratio = unsafeWindow.devicePixelRatio;
function changeQuality() {
    var uPrompt = prompt("What Quality do you desire? ("+pratio+" is the default, >6 is high, <1 is low and "+unsafeWindow.devicePixelRatio+" is the current) :", unsafeWindow.devicePixelRatio);
    if (uPrompt == null || uPrompt == "") {
        return
    } else {
        unsafeWindow.devicePixelRatio = Math.max(0.1,Number(uPrompt))
        if (unsafeWindow.devicePixelRatio > 0.1 && unsafeWindow.devicePixelRatio < pratio) {
            localStorage.devicePixelRatio = unsafeWindow.devicePixelRatio;
        } else {
            delete localStorage.devicePixelRatio;
        }
        unsafeWindow.innerHeight -= 1
        setTimeout(function(){unsafeWindow.innerHeight += 1})
    }
}

function downloadImage(data, filename = 'untitled') {
    var a = document.createElement('a');
    a.href = data;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
}

function correctToSigFig(value,reversed) {
    if (!reversed) {
        if (isNaN(value)) {
            return;
        }
        value = Number(value);
        var input = value,
            count = 0,
            len = 3;
        while (input >= 1) {
            input /= 10;
            count++;
        }
        if (count > 9) {
            value = (value / Math.pow(10, 9)).toFixed(1) + "b";
        } else if (count > 6) {
            value = (value.toFixed(1) / Math.pow(10, 6)).toFixed(1) + "m";
        } else if (count > 3) {
            value = (value.toFixed(1) / Math.pow(10, 3)).toFixed(1) + "k";
        }
    } else if (isNaN(value)){
        var num = value.match(/\d+\.?\d*/g)[0];
        var fig = value.replace(num,"");
        value = Number(num)*(fig=="k"?Math.pow(10, 3):fig=="m"?Math.pow(10, 6):fig=="b"?Math.pow(10, 9):1);
    }
    return value;
}

function updateElems() {
    inners = [`<p>•Press ${gameScene == "menu"?"[CTRL]+":""}[I] to take a screenshot</p>`,`<p>•Press ${gameScene == "menu"?"[CTRL]+":""}[U] to change the game's and screenshot's quality (${unsafeWindow.devicePixelRatio})</p>`,`<p>•Press ${gameScene == "menu"? !paused?"[CTRL]+[H] to pause the game to seek a perfect screenshot!":"[H] to play back the game":!paused?"[H] to pause the game to seek a perfect screenshot!":"[H] to play back the game"}</p>`,`<p>•Press ${gameScene == "menu"?"[CTRL]+":""}[O] to ${autoDeaSS?"disable":"enable"} auto screenshot on death if your score is over ${correctToSigFig(dopeScore)} (${autoDeaSS?"ON":"OFF"})</p>`];
    for (var i = 0; i < innerids.length; i++) {
        if (!!document.getElementById(innerids[i])) {
            document.getElementById(innerids[i]).innerHTML = inners[i];
        }
    }
    if (!!document.getElementById("menuDisp") && hasMenuDisp) {
        document.getElementById("menuDisp").innerHTML = `<p>•Use ${gameScene == "menu"?"[CTRL]+":""}[Equal] key to toggle menu display</p>`;
    }
}

function changeDeadSSScore() {
    var dopeScorePrompt = prompt("Enter the score which if reached you wish to take an automatic screenshot at your death",dopeScore);
    if (dopeScorePrompt == null) {
        return;
    } else if (dopeScorePrompt == "") {
        alert("No score entered, if you wish to cancel the protocole juste press [Escape] or click on cancel when you are requested the score");
        changeDeadSSScore();
    } else if (isNaN(dopeScorePrompt)) {
        alert("You need to enter score in full digits. (Example: 22.4k would be written as 22400)");
        changeDeadSSScore();
    } else if (!isNaN(dopeScorePrompt)) {
        dopeScore = dopeScorePrompt;
        localStorage.dopeScore = dopeScore;
        updateElems();
    }
}

GM_addStyle(`
.menu{
pointer-events: none; position: fixed; left:10px; color: rgba(255,255,255,0.5); font-style: normal; font-variant: normal;-webkit-touch-callout: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;outline: 0;
}
* {
font-family: 'Ubuntu';
}
`)
document.addEventListener("DOMContentLoaded", function() {
    if (!!localStorage.devicePixelRatio) {
        unsafeWindow.devicePixelRatio = Number(localStorage.devicePixelRatio)
        unsafeWindow.innerHeight -= 1
        setTimeout(function(){unsafeWindow.innerHeight += 1})
    }
    for (var i = 0; i < inners.length; i++) {
        var overlay = document.createElement("div");
        overlay.className = "menu";
        overlay.id = innerids[i]
        overlay.innerHTML = inners[i]
        overlay.style.top = (30+document.getElementsByClassName("menu").length*20)+"px";
        document.body.appendChild(overlay);
    }
    if (!document.getElementById('menuDisp')){
        hasMenuDisp = true;
        overlay = document.createElement("div");
        overlay.innerHTML = `<p>•Use ${gameScene == "menu"?"[CTRL]+":""}[Equal] key to toggle menu display</p>`;
        overlay.id = "menuDisp";
        overlay.style.display = "none";
        document.body.appendChild(overlay);
        setTimeout(function(){
            overlay.style.display = "block";
            overlay.style.top = (30+document.getElementsByClassName("menu").length*20)+"px";
            overlay.className = "menu";
        },100)
    }
    var menuDisp = document.getElementById('menuDisp');
    var observer = new MutationObserver(function(){
        for (var i = 0; i < document.getElementsByClassName("menu").length; i++) {
            document.getElementsByClassName("menu")[i].style.display = menuDisp.style.display;
        }
    });
    observer.observe(menuDisp, { attributes: true, childList: true });
    var pausedIcon = document.createElement("a");
    document.body.appendChild(pausedIcon);
    pausedIcon.outerHTML = `<div id="pausedIcon" style="display: none;font-size:20px;font-family: 'Ubuntu';-moz-user-select: none; -webkit-user-select: none; -ms-user-select:none; user-select:none;-o-user-select:none;"><a id="pausedText" style="position: fixed;right:${unsafeWindow.innerHeight/2-50}px;top:10px;color:red;">PAUSED [H]</a></div>`
    if (!localStorage.noalert || localStorage.noalert == "false") {
        if (!localStorage.ssDemo) {
            changeQuality()
            localStorage.ssDemo = true;
        }
    }
    document.addEventListener("keydown", function(e) {
        if(e.ctrlKey || gameScene != "menu" || e.code == "KeyH" && paused || e.code == "Equal" && menuDisp.style.display == "none") {
            if(e.code == "KeyH") {
                if (paused && !e.ctrlKey) {
                    e.preventDefault();
                }
                paused = !paused;
                updateElems();
                document.getElementById("pausedText").style.right = unsafeWindow.innerHeight/2-50+"px";
                document.getElementById("pausedIcon").style.display = paused?"block":"none";
                k[paused?"pauseMainLoop":"resumeMainLoop"]();
            } else if (e.code == "KeyU") {
                changeQuality();
                updateElems();
            } else if (e.code == "KeyI") {
                if (!(!!document.querySelector("#savess") && document.querySelector("#savess").checked)) {
                    var dataURL = k.canvas.toDataURL("image/png", 1.0);
                    downloadImage(dataURL, (localStorage.florrio_nickname||"Unnamed Flower")+' - florr.io.png');
                }
            } else if (e.code == "KeyO") {
                autoDeaSS = !autoDeaSS;
                localStorage.autoDeaSS = autoDeaSS;
                if (autoDeaSS) {
                    changeDeadSSScore();
                }
                updateElems();
            } else if (e.code == "Equal" && hasMenuDisp) {
                e.preventDefault();
                menuDisp.style.display = menuDisp.style.display != "none"? "none" : "block";
            }
        }
    })
})